Java .split weird outcome - java

I'm trying to split up a string, but it doesn't seem to give the correct output
this is the string being passed around
1#0:250:250:
I first do this
String[] dataArray = data.split("#");
this gives me
1
0:250:250:
I then do this
for( int i = 0; i < totalPlayers; i++)
{
String[] pos = dataArray[i++].split(":");
if( Integer.parseInt( pos[0] ) == ID )
{
//do nothing
}
else
{
assets[i].setPosition( Integer.parseInt( pos[1] ), Integer.parseInt( pos[2] ) );
}
}
I get an error saying ArrayIndexOutOfBoundsException, if i print out pos[0] i get 1, if i print out pos[1] i get ArrayIndexOutOfBoundsException,
Why isn't my string being split up into
0
250
250
?
Cheers
Canvas

You have an error in your code that is causing it to split 1 instead of 0:250:250: . Recall that the postfix increment operator (e.g. i++) increments the variable after it is used in the expression. So the first line in the loop is really saying String[] pos = dataArray[i].split(":"); i = i + 1; .
The simple fix would be to change i++ to ++i, which would essentially make the line run as i = i + 1; String[] pos = dataArray[i].split(":"); . However, this exact bug is why using ++ operators inside complex statements can be confusing and is often discouraged. Moreover, incrementing your loop variable outside of your for statement can lead to additional confusion.
Since the idea you really want to express is 'loop through the array by pairs', I would recommend writing something like
for (int i = 0; i < totalPlayers; i += 2) {
String[] pos = dataArray[i + 1].split(":");
// (the same as above)
}

For the first time, i will be 0. That essentially means dataArray[0], which is 1. Hence, when you do this:-
String[] pos = dataArray[i++].split(":");
Your pos has only 1 element in the array (i.e.) pos[0] which is 1. Therefore, if you try to access pos[1] or pos[2], you'll get the ArrayIndexOutOfBoundsException.

pos is created twice, once with only 1 as an element. the second time it will have 0, 250, 250.

I believe this problem is due to the fact that the split function takes a regular expression (regex).
Because the colon is a special character in regex, you must escape it with a backslash.
In Java, you must escape a backslash with another backslash.
So, try splitting on "\\:" instead of just ":"

Related

How to split a string while keeping a count of the different delimiters?

So the input looks like this {q1,q2},{a,b},{[q1:a:q2],[q2:b:q2]},q1,{q2}
A DFA pretty much.
What I would like to do is split it through the comma, brackets, and colon. then print out the results individually (ie. everything in the curly brackets have their own method).
Example:
Part1 = q1 q2
Part2 = a b
Part3 = q1 goes to q2 with a
q2 goes to q2 with b
Part4 = q1
Part5 = q2
What I was thinking was keeping a count of curly braces and if the count of curly braces =1,3,5, etc... they will execute those methods accordingly.
Problem is, when I use it as a string, I have no way of making sure it will consider "q1" as one string rather than "q" and "1"
When I split the string by using .split(\s*,\s*|\{|\}|\[|\]) it will take those characters off and I can no longer keep count of them.
Or should I just keep the curly braces, print a substring (taking off the curly brace), once it sees a close curly brace it will move to the next method.
What I've tried:
Splitting the string and storing into a list
List<String> listDFA = Arrays.asList(DFA.split("\\s*,\\s*|\\{|\\}|\\[|\\]"));
Starting DFA
for (index = 0; index<size; index++){
if (curlyBrackets.contains(listDFA.get(index))){ //curlyBrackets has "{}"
System.out.println("curly"); // just a test if it sees a curly will omit later
}
System.out.println(index); // again a test wanted to see what was being indexed
System.out.println(listDFA.get(index));
}
What I wanted to try:
for (index = 0; index <size; index++){
if (curlyBrackets.contains(DFA.substring(index, index+1))){
curly++;
if (curly == 1){
index++;
states(DFA);
}
}
}
And states() is:
public static void states (String DFA){
//List<String> stateQ = new ArrayList<String>(Arrays.asList(DFA.split(" , "))); // I tried creating the list here, but then there would be a couple of incosistent variable such as index and size.
lineVector = DFA.split(",");
int size = lineVector.length;
while(lineVector(index) != '}'){
System.out.println(stateQ[index]); //DFA.charAt(index) lineVector[index] was trying either or...
index++;
}
curly++;
I guess some kind of a hot-fix for the problem, but I still split the string using comma as a delimiter (instead of the brackets).
List<String> listDFA = Arrays.asList(DFA.split("\\s*,\\s*"));
Therefore making each content of the string be associated with an index (brackets are attached to the nearest non-comma). Then store that index into a string.
String currString = listDFA.get(index);
Then see if any part of that string has a curly bracket
if (currString.indexOf('{') != -1 || currString.indexOf('}') != -1 )
And once it matches the curly bracket condition, execute that block
if (curly <= 2){
Q.add(currString);
}
Now all I have to figure out is how to do that with square brackets since I have to store those to a 2D array

A java string exercise i came across

Look for patterns like "zip" and "zap" in the string -- length-3, starting with 'z' and ending with 'p'. Return a string where for all such words, the middle letter is gone, so "zipXzap" yields "zpXzp"
Here is a solution i got from someone:
public class Rough {
public static void main(String [] args){
StringBuffer mat = new StringBuffer("matziplzdpaztp");
for(int i = 0; i < mat.length() - 2; ++i){
if (mat.charAt(i) == 'z' & mat.charAt(i + 2) == 'p'){
mat.deleteCharAt(i + 1);
}
}
System.out.println(mat);
}
}
But why is it that the for loop condition (i < mat.length() -2) is not (i < mat.length())????
Because in the loop:
if (mat.charAt(i) == 'z' & mat.charAt(i + 2) == 'p'){
// -----------------------------------^^^^^
If i were bound by i < mat.length(), then i + 2 would be out of bounds.
Because you don't have to reach the end of your sentence since your words are at least three letters long.
"2" stands for "the length except the first word",you just need to check all the positions in the string variable , and treat the positions as the first word of the substring , so just ignore the "length of the substring without the first word".
in your case , the length of "z*p" is 3, you just check all the position in the string , and treat the position as z to check something ,so just ignore "*p" ,which has length 2.
mat.length() will give length 14 and if you check for mat.charAt(i + 2) at the end it will give java.lang.StringIndexOutOfBoundsException because the string counts from index 0 not from 1. If you still want to use mat.length() you have to replace the AND '&' operator with short circuit AND '&&' operator in if condition.

Out of Bounds Exception on a 2D Ragged Array in Java

Problem solved, I ended up need a seperate counter for the array position. Thanks for the help!
I'm writing a small app that takes a string, processes each string into 7-bits of binary code and then fills in a musical scale based on the string. For instance, if I had the binary 1000100, in the key of C Major that would give me the notes C and G(C 0 0 0 G 0 0).
I'm having an issue with a specific piece of code that takes an input of String[] (in which each element is a single character worth of binary, 7-bits) and processes each individual character in the strings themselves and stores the index number of where 1's occur in the string. For example, the string 1000100 would output 1 and 5.
Here's the method that does that:
public static String[][] convertToScale(String[] e){
String[][] notes = new String[e.length][]; //create array to hold arrays of Strings that represent notes
for(int i = 0; i < e.length; i++){
notes[i] = new String[findOccurancesOf(e[i])]; //create arrays to hold array of strings
for(int x = 0; x < e[i].length(); x++){
if((e[i].charAt(x)) != 48){ //checks to see if the char being evaluated is 0(Ascii code 48)
notes[i][x] = Integer.toString(x + 1); // if the value isn't 0, it fills in the array for that position.the value at x+1 represents the position of the scale the note is at
}
}
}
return notes;
}
Here is the code that is uses to get the occurrences of 1 in e[1]:
public static int findOccurancesOf(String s){
int counter = 0;
for(int i = 0; i < s.length(); i++ ) {
if( s.charAt(i) == 1 ) {
counter++;
}
}
return counter;
}
The issue I'm having is with the convertToScale method. When using "Hello world" as my input(the input gets converted into 7-bit binary before it gets processed by either of these methods) it passes through the 2nd for-each loop just fine the first time around, but after it tries to fill another spot in the array, it throws
java.lang.ArrayIndexOutOfBoundsException: 3
EDIT:It occurs in the line notes[i][x] = Integer.toString(x + 1); of the convertToScale method. I've run the debugger multiple times through after trying the proposes changes below and I still get the same error at the same line. The findOccurancesOf method returns the right value(When evaluating H(1001000) it returns 2.) So the thing that confuses me is that the out of bounds exception comes up right when it fills the 2nd spot in the array.
Also, feel free to tell me if anything else is crazy or my syntax is bad. Thanks!
In findOccurancesOf():
if( s.charAt(i) == 1 ) { should be if( s.charAt(i) == '1' ) { to check for the character '1'.
Otherwise it's looking for the character with ASCII value 1.
There is an out of bounds exception because if findOccuranceOf() returns the wrong value, then notes[i] is not constructed with the correct length in the following line of convertToScale():
notes[i] = new String[findOccurancesOf(e[i])];
In addition, you probably want to use something like:
notes[i][c++] = Integer.toString(x + 1);
with some counter c initialized to 0, if I understand your intentions correctly.
The reason for AIOOBE lies in this line:
notes[i] = new String[findOccurancesOf(e[i])]; //create arrays to hold array of strings
Where you call findOccurancesOf method to find occurance of 1 in your String say Hello which you dont find and return 0 and then you call notes[i][x] = Integer.toString(x + 1); with x as 0. Now since you never allocated space, you get array index out of bound exception.
I would suggest the folowing:
Validate your string before assigning the index say to be greater than 0 or something.
Initialize you notes[i] as notes[i] = new String[e[i].length];
Checking character with single quotes like a == '1' rather than a == 1
The exception is caused by what almas mentioned, note however, that your logical error is most likely inside findOccurencesOf method, if the idea was to find all the '1' chars inside a string you must change to what I outlined below, note the apostrohes. Otherwise a char is getting converted to a byte ascii code, and unless matched with a code of ascii code one, the method will return 0, causing your exception
if( s.charAt(i) == '1' ) {

convert object that holds a double to a string and then back to double

I have a two Dimensional Object array (Object[][] data) that holds pairs of products-prices.
I try to pass these values to a Map with the following way.
private String myPairs = "";
private String[] l, m;
for (int i=0; i<data.length; i++){
myPairs += (String)data[i][0] + ":" + String.valueOf(data[i][1]) + ",";
}
Map<String, Double> pairs = new java.util.HashMap<>();
l = myPairs.split(",");
for (int i=0; i<l.length; i++){
m = l[i].split(":");
pairs.put((String)m[0], Double.parseDouble((String)m[1]));
}
I get a java.lang.ArrayIndexOutOfBoundsException. What's the wrong I have done?
Try
for (int i=0; i<l.length-1; i++){
m = l[i].split(":");
pairs.put((String)m[0], Double.parseDouble((String)m[1]));
}
You problem is here:
pairs.put((String)m[0], Double.parseDouble((String)m[1]));
The first for loop creates a string that ends with a ,. For example "foo:0.1,bar:0.2,".
Then, you split by ,. So, the above example will return ["foo:0.1"; "bar:0.2"; ""]. Note the empty string value, due to the last , of the string.
Finally, for each value, you split by :. It works for the first two values (i.e. ["foo"; "0.1"] and ["bar"; "0.2"]), but the last one will be a 1-value array, containing an empty string: [""].
When trying to access the second value of the array (i.e. the index 1 since arrays are 0-based indexed), the ArrayIndexOutOfBoundsException get thrown.
Several solutions:
In the first loop, put a condition to add the , or not:
myPairs += (i == 0 ? "" : ",") + (String)data[i][0] + ":" + String.valueOf(data[i][1]);
OR Just after your first loop, remove the last char of the string:
myPairs = myPairs.substring(0, myPairs.length() - 1);
OR In the second loop, don't go until the last value, but only until the n-1 one:
for (int i=0; i<l.length - 1; i++)
OR even better, only if you don't need the string representation you're building in the first loop, replace all your code by:
for (int i=0; i<data.length; i++) {
pairs.put((String)data[i][0], Double.parseDouble((String)data[i][1]));
}
When the first for-loop ends, you have all the pairs separated with ',' and an extra ',' in the end. So, l.length is the number of pairs plus one. Though, this shouldn't produce an error so far.
The problem is that when you split every pair on ':', the last element of l is equal to a blank string.
So the splitting produces an 1-element-array, containing a blank string. The error occures because you ask for m[1].
Try not adding the ',' after the last element of the pairs, and the problem should be solved.
I hope this helps :)
The last element in the split of ,s is empty (because you say + "," on the last iteration of the first loop), so skip the last element in the second loop.
for (int i = 0; i < l.length-1; i++)
{
m = l[i].split(":");
pairs.put((String)m[0], Double.parseDouble((String)m[1]));
}
Also note that if the supplied strings contains :s or ,s, your algorithm would probably throw an exception too.
Note - A way better way (and to avoid the above) would just be to do it in the first loop, something like:
for (int i = 0; i < data.length; i++)
{
pairs.put((String)data[i][0], Double.parseDouble((String)data[i][1]));
}

Java characters count in an array

Another problem I try to solve (NOTE this is not a homework but what popped into my head), I'm trying to improve my problem-solving skills in Java. I want to display this:
Students ID #
Carol McKane 920 11
James Eriol 154 10
Elainee Black 462 12
What I want to do is on the 3rd column, display the number of characters without counting the spaces. Give me some tips to do this. Or point me to Java's robust APIs, cause I'm not yet that familiar with Java's string APIs. Thanks.
It sounds like you just want something like:
public static int countNonSpaces(String text) {
int count = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) != ' ') {
count++;
}
}
return count;
}
You may want to modify this to use Character.isWhitespace instead of only checking for ' '. Also note that this will count pairs outside the Basic Multilingual Plane as two characters. Whether that will be a problem for you or not depends on your use case...
Think of solving a problem and presenting the answer as two very different steps. I won't help you with the presentation in a table, but to count the number of characters in a String (without spaces) you can use this:
String name = "Carol McKane";
int numberOfCharacters = name.replaceAll("\\s", "").length();
The regular expression \\s matches all whitespace characters in the name string, and replaces them with "", or nothing.
Probably the shortest and easiest way:
String[][] students = { { "Carol McKane", "James Eriol", "Elainee Black" }, { "920", "154", "462" } };
for (int i = 0 ; i < students[0].length; i++) {
System.out.println(students[0][i] + "\t" + students[1][i] + "\t" + students[0][i].replace( " ", "" ).length() );
}
replace(), replaces each substring (" ") of your string and removes it from the result returned, from this temporal string, without spaces, you can get the length by calling length() on it...
The String name will remain unchanged.
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
cheers
To learn more about it you should watch the API documentation for String and Character
Here some examples how to do:
// variation 1
int count1 = 0;
for (char character : text.toCharArray()) {
if (Character.isLetter(character)) {
count1++;
}
}
This uses a special short from of "for" instruction. Here's the long form for better understanding:
// variation 2
int count2 = 0;
for (int i = 0; i < text.length(); i++) {
char character = text.charAt(i);
if (Character.isLetter(character)) {
count2++;
}
}
BTW, removing whitespaces via replace method is not a good coding style to me and not quite helpful for understanding how string class works.

Categories