How to split numbers in java? - java

I am trying to split number but don't know how to do this.
I referred this link.
https://stackoverflow.com/a/12297231/1395259
Suppose I have a number 12345678.
using above link I am splitting by 3 places.So the output becomes 123 456 78.
But I want it as 12 345 678 And I want to take the string that was split in the form 12.345.678 .
Can anybody help me please??

java.text package provides all reasonable options for formatting numbers
DecimalFormat f = new DecimalFormat("#,###");
DecimalFormatSymbols fs = f.getDecimalFormatSymbols();
fs.setGroupingSeparator('.');
f.setDecimalFormatSymbols(fs);
String s = f.format(12345678);
System.out.println(s);
output
12.345.678
using DecimalFormat directly is very flexible, but typically we can use a shorter version
String s = NumberFormat.getNumberInstance(Locale.GERMAN).format(12345678);
which produces the same string
12.345.678
Different countries have different rules for formatting numbers (and dates). Usually we want our programs to be internationalized / localized and use default locale version
NumberFormat.getNumberInstance().format(number);

One lazy way is to reverse the string, apply above method, and then reverse it again.
You can use StringBuffer's Reverse Function, as shown in Reverse each individual word of "Hello World" string with Java
12345678
87654321
876 543 21
12 345 678
I am assuming of course that you want to split by 3s and the group with <3 digits left appears in the start rather than the end as in the method you link.
The not so lazy way would be to use string length to adapt the method you link to start with length%3 characters.

Using the solution from your link i would rephrase that as following (TESTED!):
public String[] splitStringEvery(String s, int interval) {
int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
String[] result = new String[arrayLength];
int j = s.length();
int lastIndex = result.length;
for (int i = lastIndex - 1; i > 0; i--) {
result[i] = s.substring(j - interval, j);
j -= interval;
} //Add the last bit
result[0] = s.substring(0, j);
return result;
}

Here is a method that splits an int value and returns an String in the specified format:
public static String split( int n ) {
String result = "", s = Integer.toString( n );
while ( s.length() > 3 ) {
result = s.substring( s.length() -3, s.length() ) + ((result.length() > 0)? "." + result : "" );
s = s.substring( 0, s.length() -3 );
}
return s + "." + result;
}
Input:
12345678
Output:
12.345.678

If it's a String, use StringBuilder or StringBuffer. Here's the code:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
String numberStrBefore = Integer.toString(number);
StringBuffer numberStrAfter = new StringBuffer();
numberStrAfter.append(numberStrBefore.charAt(0));
numberStrAfter.append(numberStrBefore.charAt(1));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(2));
numberStrAfter.append(numberStrBefore.charAt(3));
numberStrAfter.append(numberStrBefore.charAt(4));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(5));
numberStrAfter.append(numberStrBefore.charAt(6));
numberStrAfter.append(numberStrBefore.charAt(7));
System.out.println("Number Before: " + numberStrBefore);
System.out.println("Number After: " + numberStrAfter.toString());
}
}
And here is the same thing with a method:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
int[] split = {2,3,3}; //How to split the number
String numberStrAfter = insertDots(number, split);
System.out.println("Number Before: " + number);
System.out.println("Number After: " + numberStrAfter);
}
public static String insertDots(int number, int[] split){
StringBuffer numberStrAfter = new StringBuffer();
String numberStr = Integer.toString(number);
int currentIndex = 0;
for(int i = 0; i < split.length; i++){
for(int j = 0; j < split[i]; j++){
numberStrAfter.append(numberStr.charAt(currentIndex));
currentIndex++;
}
numberStrAfter.append('.');
}
numberStrAfter.deleteCharAt(numberStrAfter.length()-1); //Removing last "."
return numberStrAfter.toString();
}
}
This version, with the method, allows you to split any number into any format that you want, simply change the "split" variable into the format that you want to split the string into. (Ex: Splitting 12345678 into: 1.1234.5.67.8 would mean that "split" must be set to {1,4,1,2,1}).

Related

How can I format a two row string so that items of the bottom row line up with items of the top row in java

So I have something set up like this:
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String lame = ("3 5 6 7 8");
String total = (fun + "\n" + lame);
System.out.println(total);
}
How can I format the total string so that when it prints it prints like this:
3000.05 500 6000.987 70 8000.00
3 5 6 7 8
I've been looking forever and can't seem to find what i'm looking for. I'm just trying to right align each part of the bottom string to the farthest part of the top string.
you can use a for loop to go through each position on the string and create a new String to store what you are looking for. Ex.
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String newStringToBePrinted="";
for(char c: fun){
if (!(c == ' '|| c == '.')){
String ch = c+"";
newStringToBePrinted+= ch;
} else{
newStringToBePrinted+="-";
}
}
String total = (fun + "\n" + newStringToBePrinted);
System.out.println(total);
}
hope this helps.
Here is how you can do this with (moderately) readable Stream code. The below method will work, but it's a bit ugly because AFAIK Java 8 does not yet have a clean 'zip' function for streams.
As well, because of the way String.format() works, I had to pad the first thing in the list separately, which is also kind of yucky, but I couldn't quickly think of a way to make it all fit.
private String formatStringPairs(String firstLine, String secondLine, String delimiter) {
String[] firstLineArray = firstLine.split(delimiter);
String[] secondLineArray = secondLine.split(delimiter);
String formattedStringPairs =
String.format("%" + firstLineArray[0].length() + "s", secondLineArray[0]) +
IntStream.range(1, firstLineArray.length)
.mapToObj(index -> String.format("%" + (firstLineArray[index].length() + 1) + "s", secondLineArray[index]))
.reduce("", String::concat);
return firstLine + "\n" + formattedStringPairs;
}
I look forward to seeing someone post a cleaner and better way!
This should work. I believe temp is the recreation of your variable lame but the code would be the same.
package funTest;
public class funT {
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String s2 = new String(fun);
char first=' ';
String temp="";
for (int i = 0;i < s2.length(); i++){
System.out.println("Should be: 3,5,6,7,8");
//gets first
if (i!=0){
if (s2.charAt(i)==' '){
first=s2.charAt(i+1);
}
}else{
first=s2.charAt(i);
}
System.out.println("First = "+first);
/////
//add spaces
if (s2.charAt(i)!=' '){
temp+=' ';
}
if (i<s2.length()-1&&s2.charAt(i+1)==' '){
temp+=first;
} else if (i==s2.length()-1){
temp+=first;
}
}
temp = temp.substring(1);
System.out.println(s2+"\n"+temp);
}
}
Ok so tldr. Use the .format() method of PrintStream (for byte streams) or PrintWriter (for char streams)
Luckily System.out is one of these objects. Documentation for format can be found here
Here is a nice demonstration of using .format() I mentioned for your purpose, this code assumes the two strings have an equal number of numbers separated by whitespace. It also assumes that the second-row item length will be <= in length to its' first-row counterpart
public static void main(String[] args)
{
String fun = "3000.05 500 6000.987 70 8000.00";
String lame = "3 5 6 7 8";
String[] funs = fun.split(" ");
String[] lames = lame.split(" ");
for(String s : funs)
{
System.out.printf("%s\t", s);
}
System.out.printf("%n");
for(int i = 0; i < lames.length; i++) //use index iterator so we can get le funz
{
System.out.printf("%" + funs[i].length() + "s\t", lames[i]);
}
System.out.printf("%n");
}
Output:
run:
3000.05 500 6000.987 70 8000.00
3 5 6 7 8
BUILD SUCCESSFUL (total time: 0 seconds)
To improve this code more It might be possible to associate the first row and second row in a Map type object, and then when printing: set the padding size
to the size of the entry key or value which has the greatest length. Also add a handler for empty entries.

Getting the last integer from a string

Say I have a string 3 + 4 = 7 or 23 - 4 = 19. I'm wondering how I would go about getting the last integer from the string so that it can be compared to another int.
Ive used this code:
int first = Integer.parseInt(str.substring(0, str.indexOf(" ")));
int second = Integer.parseInt(result.substring(result.indexOf('+')+1 , result.indexOf('=')));
to get the first and second integers for computation, but I can't seem to get the last integer in string when I'm using the method above. Is it just something I'm doing wrong or is there something else I need to do?
I also cannot use arrays, regex, try/catch, or a SystemTokenizer.
And my strings will not always be in the a + b = c format with the spaces or a single digit integer.
the strings are taken from a text file that is imported by the scanner. Here's a sample of the equations in the file:
11 - 2 = 9
12 - 1 = 11
7 + 1 = 8
7 - 3 = 4
7 + 2 = 9
14 + 4 = 18
If all of your strings are in this format - a + b = c, then there is a simple way -
String[] parts = str.split("=");
String lastDigit = parts[parts.length - 1].trim();
int last = Integer.parseInt(lastDigit);
Check out the docs.
Update
As per your requirement of not wanting to use regex, you can do something like this -
public int getLastDigit(String expression) {
StringBuffer result = new StringBuffer();
for (int i = expression.length() - 1; i >= 0; i--) {
char c = expression.charAt(i);
if (c == '=') {
break;
}
else {
result.append(c);
}
}
return Integer.parseInt(result.reverse()
.toString()
.trim());
}
int last = getLastDigit("1 + 3 = 14");
System.out.println(last); // will print 14
This will work a lot easier:
String[] tokens = str.Split(" ");
int first = Integer.parseInt(tokens[0]);
int second = Integer.parseInt(tokens[1]);
int last = Integer.parseInt(tokens[3]);
Otherwise without arrays, use lastIndexOf:
int last = Integer.parseInt(str.substring(str.lastIndexOf(" "), str.length()));
simple use split and get index[1] to get last integer in string
just split with "="
Does this work?
int last = Integer.parseInt(str.substring(str.indexOf("=") + 1, str.length));
The idea is to get the index of the "=", and then parse the substring of there to the end.
I did "str.indexOf("=") + 1" so that it didn't include the "sign".
String [] tokens = str.split("=");
String finalDigit = tokens[tokens.length-1];
You would need trim the extracted digit, other wise it is possible to throw
Exception in thread "main" java.lang.NumberFormatException: For input
string: " 7"
To extract the last digit, you may follow the below code
String str1="3 + 4 = 7";
String str2= str1.substring(str1.lastIndexOf("=")+1).trim();
int i = Integer.parseInt(str2);
import java.io.*;
class GetString{
publice static void main(String []args)
{
string str,int x;
Scanner s = new Scanner(input).useDelimiter("\n"); //take each line
while((str=s.next())!=NULL)
{
str.trim();
int first = Integer.parseInt(str.substring(0, str.indexOf(" ")));
//Depending on weather the sign is '+' or '-' it will take the index of that
int second = Integer.parseInt(str.substring((x=str.indexOf('+')>-1?
str.indexOf('+'):str.indexOf('-'))+1 , result.indexOf('=')));
int Third= Integer.parseInt(str.substring(str.indexOf("="), str.Length-1))
}
s.close();
}
}
Its a general idea not a perfect code.Edits and suggestions are welcome.

how to count the spaces in a java string?

I need to count the number of spaces in my string but my code gives me a wrong number when i run it, what is wrong?
int count=0;
String arr[]=s.split("\t");
OOPHelper.println("Number of spaces are: "+arr.length);
count++;
s.length() - s.replaceAll(" ", "").length() returns you number of spaces.
There are more ways. For example"
int spaceCount = 0;
for (char c : str.toCharArray()) {
if (c == ' ') {
spaceCount++;
}
}
etc., etc.
In your case you tried to split string using \t - TAB. You will get right result if you use " " instead. Using \s may be confusing since it matches all whitepsaces - regular spaces and TABs.
Here is a different way of looking at it, and it's a simple one-liner:
int spaces = s.replaceAll("[^ ]", "").length();
This works by effectively removing all non-spaces then taking the length of what’s left (the spaces).
You might want to add a null check:
int spaces = s == null ? 0 : s.replaceAll("[^ ]", "").length();
Java 8 update
You can use a stream too:
long spaces = s.chars().filter(c -> c == (int)' ').count();
Fastest way to do this would be:
int count = 0;
for(int i = 0; i < str.length(); i++) {
if(Character.isWhitespace(str.charAt(i))) count++;
}
This would catch all characters that are considered whitespace.
Regex solutions require compiling regex and excecuting it - with a lot of overhead. Getting character array requires allocation. Iterating over byte array would be faster, but only if you are sure that your characters are ASCII.
\t will match tabs, rather than spaces and should also be referred to with a double slash: \\t. You could call s.split( " " ) but that wouldn't count consecutive spaces. By that I mean...
String bar = " ba jfjf jjj j ";
String[] split = bar.split( " " );
System.out.println( split.length ); // Returns 5
So, despite the fact there are seven space characters, there are only five blocks of space. It depends which you're trying to count, I guess.
Commons Lang is your friend for this one.
int count = StringUtils.countMatches( inputString, " " );
If you use Java 8, the following should work:
long count = "0 1 2 3 4.".chars().filter(Character::isWhitespace).count();
This will also work in Java 8 using Eclipse Collections:
int count = Strings.asChars("0 1 2 3 4.").count(Character::isWhitespace);
Note: I am a committer for Eclipse Collections.
Your code will count the number of tabs and not the number of spaces. Also, the number of tabs will be one less than arr.length.
Another way using regular expressions
int length = text.replaceAll("[^ ]", "").length();
The code you provided would print the number of tabs, not the number of spaces. The below function should count the number of whitespace characters in a given string.
int countSpaces(String string) {
int spaces = 0;
for(int i = 0; i < string.length(); i++) {
spaces += (Character.isWhitespace(string.charAt(i))) ? 1 : 0;
}
return spaces;
}
A solution using java.util.regex.Pattern / java.util.regex.Matcher
String test = "foo bar baz ";
Pattern pattern = Pattern.compile(" ");
Matcher matcher = pattern.matcher(test);
int count = 0;
while (matcher.find()) {
count++;
}
System.out.println(count);
please check the following code, it can help
public class CountSpace {
public static void main(String[] args) {
String word = "S N PRASAD RAO";
String data[];int k=0;
data=word.split("");
for(int i=0;i<data.length;i++){
if(data[i].equals(" ")){
k++;
}
}
System.out.println(k);
}
}
The simple and fastest way to count spaces
String fav="foo hello me hi";
for( int i=0; i<fav.length(); i++ ) {
if(fav.charAt(i) == ' ' ) {
counter++;
}
}
I just had to do something similar to this and this is what I used:
String string = stringValue;
String[] stringArray = string.split("\\s+");
int length = stringArray.length;
System.out.println("The number of parts is: " + length);
public static void main(String[] args) {
String str = "Honey dfd tEch Solution";
String[] arr = str.split(" ");
System.out.println(arr.length);
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (!arr[i].trim().isEmpty()) {
System.out.println(arr[i]);
count++;
}
}
System.out.println(count);
}
public static void main(String[] args) {
Scanner input= new Scanner(System.in);`
String data=input.nextLine();
int cnt=0;
System.out.println(data);
for(int i=0;i<data.length()-1;i++)
{if(data.charAt(i)==' ')
{
cnt++;
}
}
System.out.println("Total number of Spaces in a given String are " +cnt);
}
This program will definitely help you.
class SpaceCount
{
public static int spaceCount(String s)
{ int a=0;
char ch[]= new char[s.length()];
for(int i = 0; i < s.length(); i++)
{ ch[i]= s.charAt(i);
if( ch[i]==' ' )
a++;
}
return a;
}
public static void main(String... s)
{
int m = spaceCount("Hello I am a Java Developer");
System.out.println("The number of words in the String are : "+m);
}
}
The most precise and exact plus fastest way to that is :
String Name="Infinity War is a good movie";
int count =0;
for(int i=0;i<Name.length();i++){
if(Character.isWhitespace(Name.charAt(i))){
count+=1;
}
}
System.out.println(count);
import java.util.Scanner;
import java.io.*;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in).useDelimiter("\n");
String str = sc.next();
int spaceCount=0;
str = str.toLowerCase();
for(int i = 0; i < str.length(); i++) {
if(str.charAt(i)==' '){
spaceCount++;
}
}
System.out.println("Number of spaces: "+ spaceCount);
}
}

Adding dots into a system.out.println

well basically I have a line thats has a finial in of 40,
if a add 2 words that are 10 letters each long that leaves me with 20 spaces
thouse 20 spaces should be filled with dots ...... for example
hello................................you
or
stack...........................overflow
now I have the code working fine, I just have no idea on how to please this in a system.out.println so that the result is printed to the console.
I was thinking of using a whileloop to print the dots one at a time, after testing how many number of dots there should be once bother words are entered.
At the moment I have this which clearly doesn't work
{
System.out.println (word1 + ".." + word2);
while (wordlegnth1 + wordlegnth2 < LINELENGTH)
{
System.out.println (word1 + "." + word2);
wordlegnth1++;
}
final int LINE_LENGTH = 40;
String word1 = ...;
String word2 = ...;
StringBuilder sb = new StringBuilder(LINE_LENGTH);
sb.append(word1);
for (int i = 0; i + word1.length() + word2.length() < LINE_LENGTH; i++) {
sb.append(".");
}
sb.append(word2);
System.out.println(sb.toString());
Note: the use of StringBuilder is to avoid performance penalty due to String immutability
/**
* Formats a given string to 40 characters by prefixing it with word1 and
* suffixing it with word2 and using dots in the middle to make length of final
* string = 40.
* If string will not fit in 40 characters, -1 is returned, otherwise 0 is
* returned.
*
* #param word1 the first word
* #param word2 the second word
* #return 0 if string will fit in 40 characters, -1 otherwise
*/
public static int formatString(String word1, String word2) {
final int LINELENGTH = 40;
// determine how many dots we need
int diff = LINELENGTH - (word1.length() + word2.length());
if (diff < 0) {
// it's too big
System.out.println("string is too big to fit");
return -1;
}
// add the dots
StringBuilder dots = new StringBuilder();
for (int i = 0; i < diff; ++i) {
dots.append(".");
}
// build the final result
String result = word1 + dots.toString() + word2;
System.out.println(result);
return 0;
}
public static void main(String[] args) throws Throwable {
formatString("stack", "overflow");
String str = "";
for (int i = 0; i < 21; ++i) {
str += "a";
}
formatString(str, str);
}
Output:
stack...........................overflow
string is too big to fit
Why not start with something like:
int lengthA = word1.length();
int lengthB = word2.length();
int required = LINE_LENGHT - (lengthA + lengthB);
for(int i = 0; i < required; i++)
{
System.out.print(".");
}
It can be improved on (try strings that are very large for example, or use a StringBuilder rather than System.out.print).
add apache's commons-lang to your classpath and use StringUtils.leftPad()
System.out.println(str1 + StringUtils.leftPad(str2, 40 - str1.length(), '.'));
why write a method to do something someone else has already written + tested?

Split string to equal length substrings in Java

How to split the string "Thequickbrownfoxjumps" to substrings of equal size in Java.
Eg. "Thequickbrownfoxjumps" of 4 equal size should give the output.
["Theq","uick","brow","nfox","jump","s"]
Similar Question:
Split string into equal-length substrings in Scala
Here's the regex one-liner version:
System.out.println(Arrays.toString(
"Thequickbrownfoxjumps".split("(?<=\\G.{4})")
));
\G is a zero-width assertion that matches the position where the previous match ended. If there was no previous match, it matches the beginning of the input, the same as \A. The enclosing lookbehind matches the position that's four characters along from the end of the last match.
Both lookbehind and \G are advanced regex features, not supported by all flavors. Furthermore, \G is not implemented consistently across the flavors that do support it. This trick will work (for example) in Java, Perl, .NET and JGSoft, but not in PHP (PCRE), Ruby 1.9+ or TextMate (both Oniguruma). JavaScript's /y (sticky flag) isn't as flexible as \G, and couldn't be used this way even if JS did support lookbehind.
I should mention that I don't necessarily recommend this solution if you have other options. The non-regex solutions in the other answers may be longer, but they're also self-documenting; this one's just about the opposite of that. ;)
Also, this doesn't work in Android, which doesn't support the use of \G in lookbehinds.
Well, it's fairly easy to do this with simple arithmetic and string operations:
public static List<String> splitEqually(String text, int size) {
// Give the list the right capacity to start with. You could use an array
// instead if you wanted.
List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);
for (int start = 0; start < text.length(); start += size) {
ret.add(text.substring(start, Math.min(text.length(), start + size)));
}
return ret;
}
Note: this assumes a 1:1 mapping of UTF-16 code unit (char, effectively) with "character". That assumption breaks down for characters outside the Basic Multilingual Plane, such as emoji, and (depending on how you want to count things) combining characters.
I don't think it's really worth using a regex for this.
EDIT: My reasoning for not using a regex:
This doesn't use any of the real pattern matching of regexes. It's just counting.
I suspect the above will be more efficient, although in most cases it won't matter
If you need to use variable sizes in different places, you've either got repetition or a helper function to build the regex itself based on a parameter - ick.
The regex provided in another answer firstly didn't compile (invalid escaping), and then didn't work. My code worked first time. That's more a testament to the usability of regexes vs plain code, IMO.
This is very easy with Google Guava:
for(final String token :
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps")){
System.out.println(token);
}
Output:
Theq
uick
brow
nfox
jump
s
Or if you need the result as an array, you can use this code:
String[] tokens =
Iterables.toArray(
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps"),
String.class
);
Reference:
Splitter.fixedLength()
Splitter.split()
Iterables.toArray()
Note: Splitter construction is shown inline above, but since Splitters are immutable and reusable, it's a good practice to store them in constants:
private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4);
// more code
for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
System.out.println(token);
}
If you're using Google's guava general-purpose libraries (and quite honestly, any new Java project probably should be), this is insanely trivial with the Splitter class:
for (String substring : Splitter.fixedLength(4).split(inputString)) {
doSomethingWith(substring);
}
and that's it. Easy as!
public static String[] split(String src, int len) {
String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
for (int i=0; i<result.length; i++)
result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
return result;
}
public String[] splitInParts(String s, int partLength)
{
int len = s.length();
// Number of parts
int nparts = (len + partLength - 1) / partLength;
String parts[] = new String[nparts];
// Break into parts
int offset= 0;
int i = 0;
while (i < nparts)
{
parts[i] = s.substring(offset, Math.min(offset + partLength, len));
offset += partLength;
i++;
}
return parts;
}
Here's a one-liner version which uses Java 8 IntStream to determine the indexes of the slice beginnings:
String x = "Thequickbrownfoxjumps";
String[] result = IntStream
.iterate(0, i -> i + 4)
.limit((int) Math.ceil(x.length() / 4.0))
.mapToObj(i ->
x.substring(i, Math.min(i + 4, x.length())
)
.toArray(String[]::new);
I'd rather this simple solution:
String content = "Thequickbrownfoxjumps";
while(content.length() > 4) {
System.out.println(content.substring(0, 4));
content = content.substring(4);
}
System.out.println(content);
A StringBuilder version:
public static List<String> getChunks(String s, int chunkSize)
{
List<String> chunks = new ArrayList<>();
StringBuilder sb = new StringBuilder(s);
while(!(sb.length() ==0))
{
chunks.add(sb.substring(0, chunkSize));
sb.delete(0, chunkSize);
}
return chunks;
}
i use the following java 8 solution:
public static List<String> splitString(final String string, final int chunkSize) {
final int numberOfChunks = (string.length() + chunkSize - 1) / chunkSize;
return IntStream.range(0, numberOfChunks)
.mapToObj(index -> string.substring(index * chunkSize, Math.min((index + 1) * chunkSize, string.length())))
.collect(toList());
}
You can use substring from String.class (handling exceptions) or from Apache lang commons (it handles exceptions for you)
static String substring(String str, int start, int end)
Put it inside a loop and you are good to go.
In case you want to split the string equally backwards, i.e. from right to left, for example, to split 1010001111 to [10, 1000, 1111], here's the code:
/**
* #param s the string to be split
* #param subLen length of the equal-length substrings.
* #param backwards true if the splitting is from right to left, false otherwise
* #return an array of equal-length substrings
* #throws ArithmeticException: / by zero when subLen == 0
*/
public static String[] split(String s, int subLen, boolean backwards) {
assert s != null;
int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1;
String[] strs = new String[groups];
if (backwards) {
for (int i = 0; i < groups; i++) {
int beginIndex = s.length() - subLen * (i + 1);
int endIndex = beginIndex + subLen;
if (beginIndex < 0)
beginIndex = 0;
strs[groups - i - 1] = s.substring(beginIndex, endIndex);
}
} else {
for (int i = 0; i < groups; i++) {
int beginIndex = subLen * i;
int endIndex = beginIndex + subLen;
if (endIndex > s.length())
endIndex = s.length();
strs[i] = s.substring(beginIndex, endIndex);
}
}
return strs;
}
Here is a one liner implementation using Java8 streams:
String input = "Thequickbrownfoxjumps";
final AtomicInteger atomicInteger = new AtomicInteger(0);
Collection<String> result = input.chars()
.mapToObj(c -> String.valueOf((char)c) )
.collect(Collectors.groupingBy(c -> atomicInteger.getAndIncrement() / 4
,Collectors.joining()))
.values();
It gives the following output:
[Theq, uick, brow, nfox, jump, s]
Java 8 solution (like this but a bit simpler):
public static List<String> partition(String string, int partSize) {
List<String> parts = IntStream.range(0, string.length() / partSize)
.mapToObj(i -> string.substring(i * partSize, (i + 1) * partSize))
.collect(toList());
if ((string.length() % partSize) != 0)
parts.add(string.substring(string.length() / partSize * partSize));
return parts;
}
Use code points to handle all characters
Here is a solution:
Works with all 143,859 Unicode characters
Allows you to examine or manipulate each resulting string, if you have further logic to process.
To work with all Unicode characters, avoid the obsolete char type. And avoid char-based utilities. Instead, use code point integer numbers.
Call String#codePoints to get an IntStream object, a stream of int values. In the code below, we collect those int values into an array. Then we loop the array, for each integer we append the character assigned to that number to our StringBuilder object. Every nth character, we add a string to our master list, and empty the StringBuilder.
String input = "Thequickbrownfoxjumps";
int chunkSize = 4 ;
int[] codePoints = input.codePoints().toArray(); // `String#codePoints` returns an `IntStream`. Collect the elements of that stream into an array.
int initialCapacity = ( ( codePoints.length / chunkSize ) + 1 );
List < String > strings = new ArrayList <>( initialCapacity );
StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < codePoints.length ; i++ )
{
sb.appendCodePoint( codePoints[ i ] );
if ( 0 == ( ( i + 1 ) % chunkSize ) ) // Every nth code point.
{
strings.add( sb.toString() ); // Remember this iteration's value.
sb.setLength( 0 ); // Clear the contents of the `StringBuilder` object.
}
}
if ( sb.length() > 0 ) // If partial string leftover, save it too. Or not… just delete this `if` block.
{
strings.add( sb.toString() ); // Remember last iteration's value.
}
System.out.println( "strings = " + strings );
strings = [Theq, uick, brow, nfox, jump, s]
This works with non-Latin characters. Here we replace q with FACE WITH MEDICAL MASK.
String text = "The😷uickbrownfoxjumps"
strings = [The😷, uick, brow, nfox, jump, s]
Here is my version based on RegEx and Java 8 streams. It's worth to mention that Matcher.results() method is available since Java 9.
Test included.
public static List<String> splitString(String input, int splitSize) {
Matcher matcher = Pattern.compile("(?:(.{" + splitSize + "}))+?").matcher(input);
return matcher.results().map(MatchResult::group).collect(Collectors.toList());
}
#Test
public void shouldSplitStringToEqualLengthParts() {
String anyValidString = "Split me equally!";
String[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"};
String[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"};
Assert.assertArrayEquals(expectedTokens2, splitString(anyValidString, 2).toArray());
Assert.assertArrayEquals(expectedTokens3, splitString(anyValidString, 3).toArray());
}
The simplest solution is:
/**
* Slices string by passed - in slice length.
* If passed - in string is null or slice length less then 0 throws IllegalArgumentException.
* #param toSlice string to slice
* #param sliceLength slice length
* #return List of slices
*/
public static List<String> stringSlicer(String toSlice, int sliceLength) {
if (toSlice == null) {
throw new IllegalArgumentException("Passed - in string is null");
}
if (sliceLength < 0) {
throw new IllegalArgumentException("Slice length can not be less then 0");
}
if (toSlice.isEmpty() || toSlice.length() <= sliceLength) {
return List.of(toSlice);
}
return Arrays.stream(toSlice.split(String.format("(?s)(?<=\\G.{%d})", sliceLength))).collect(Collectors.toList());
}
I asked #Alan Moore in a comment to the accepted solution how strings with newlines could be handled. He suggested using DOTALL.
Using his suggestion I created a small sample of how that works:
public void regexDotAllExample() throws UnsupportedEncodingException {
final String input = "The\nquick\nbrown\r\nfox\rjumps";
final String regex = "(?<=\\G.{4})";
Pattern splitByLengthPattern;
String[] split;
splitByLengthPattern = Pattern.compile(regex);
split = splitByLengthPattern.split(input);
System.out.println("---- Without DOTALL ----");
for (int i = 0; i < split.length; i++) {
byte[] s = split[i].getBytes("utf-8");
System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
}
/* Output is a single entry longer than the desired split size:
---- Without DOTALL ----
[Idx: 0, length: 26] - [B#17cdc4a5
*/
//DOTALL suggested in Alan Moores comment on SO: https://stackoverflow.com/a/3761521/1237974
splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL);
split = splitByLengthPattern.split(input);
System.out.println("---- With DOTALL ----");
for (int i = 0; i < split.length; i++) {
byte[] s = split[i].getBytes("utf-8");
System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
}
/* Output is as desired 7 entries with each entry having a max length of 4:
---- With DOTALL ----
[Idx: 0, length: 4] - [B#77b22abc
[Idx: 1, length: 4] - [B#5213da08
[Idx: 2, length: 4] - [B#154f6d51
[Idx: 3, length: 4] - [B#1191ebc5
[Idx: 4, length: 4] - [B#30ddb86
[Idx: 5, length: 4] - [B#2c73bfb
[Idx: 6, length: 2] - [B#6632dd29
*/
}
But I like #Jon Skeets solution in https://stackoverflow.com/a/3760193/1237974 also. For maintainability in larger projects where not everyone are equally experienced in Regular expressions I would probably use Jons solution.
Another brute force solution could be,
String input = "thequickbrownfoxjumps";
int n = input.length()/4;
String[] num = new String[n];
for(int i = 0, x=0, y=4; i<n; i++){
num[i] = input.substring(x,y);
x += 4;
y += 4;
System.out.println(num[i]);
}
Where the code just steps through the string with substrings
import static java.lang.System.exit;
import java.util.Scanner;
import Java.util.Arrays.*;
public class string123 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("Enter String");
String r=sc.nextLine();
String[] s=new String[10];
int len=r.length();
System.out.println("Enter length Of Sub-string");
int l=sc.nextInt();
int last;
int f=0;
for(int i=0;;i++){
last=(f+l);
if((last)>=len) last=len;
s[i]=r.substring(f,last);
// System.out.println(s[i]);
if (last==len)break;
f=(f+l);
}
System.out.print(Arrays.tostring(s));
}}
Result
Enter String
Thequickbrownfoxjumps
Enter length Of Sub-string
4
["Theq","uick","brow","nfox","jump","s"]
#Test
public void regexSplit() {
String source = "Thequickbrownfoxjumps";
// define matcher, any char, min length 1, max length 4
Matcher matcher = Pattern.compile(".{1,4}").matcher(source);
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(source.substring(matcher.start(), matcher.end()));
}
String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"};
assertArrayEquals(result.toArray(), expected);
}
public static String[] split(String input, int length) throws IllegalArgumentException {
if(length == 0 || input == null)
return new String[0];
int lengthD = length * 2;
int size = input.length();
if(size == 0)
return new String[0];
int rep = (int) Math.ceil(size * 1d / length);
ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_16LE));
String[] out = new String[rep];
byte[] buf = new byte[lengthD];
int d = 0;
for (int i = 0; i < rep; i++) {
try {
d = stream.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
if(d != lengthD)
{
out[i] = new String(buf,0,d, StandardCharsets.UTF_16LE);
continue;
}
out[i] = new String(buf, StandardCharsets.UTF_16LE);
}
return out;
}
public static List<String> getSplittedString(String stringtoSplit,
int length) {
List<String> returnStringList = new ArrayList<String>(
(stringtoSplit.length() + length - 1) / length);
for (int start = 0; start < stringtoSplit.length(); start += length) {
returnStringList.add(stringtoSplit.substring(start,
Math.min(stringtoSplit.length(), start + length)));
}
return returnStringList;
}

Categories

Resources