How do I get this for loop to work right? - java

i don't know how to do something specific at the last loop of this for loop:
String msg = "---Player List, Count:" + users.size() + "---" + brln;
for (int i = 0; i < users.size(); i++) {
if((i - 1) == users.size()){
msg += "--::" + users.get(i).name; //Do this at the last loop
return; //returns the void
}
msg += "--::" + users.get(i).name + brln; // do this by default
}
Can you help me get this to work?

Your condition is wrong: instead of (i - 1) == users.size() use (i + 1) == users.size() or i == users.size() - 1.
Basically (i - 1) == users.size() would match the element after the last (which clearly doesn't exist), i.e. for a list of size 5 you'd get (i - 1) == 5 or i == 6.
In the example above (i + 1) == users.size() and i == users.size() - 1 would resolve to (i + 1) == 5 and i == 5 - 1 which both result in i == 4, which is the last index in the list.
Edit: Btw, your loop is still quite odd. You basically seem to add a line break after each but the last element. Why don't you change it to something like this:
String msg = "---Player List, Count:" + users.size() + "---" + brln;
for (int i = 0; i < users.size(); i++) {
if( i > 0){
msg += brln;
}
msg += "--::" + users.get(i).name;
}
This would add a line break before every line except the first. Note how the condition is much easier.

Change this
from:
if((i - 1) == users.size()){
to:
if((i + 1) == users.size()){

What you want in effect is a string of entries separated by a delimiter, where the delimiter is a line break. Use this idiom:
String delimiter = "", result = "";
for (...loop init...) {
result += delimiter;
...append one entry...
delimiter = brln;
}
Other than that, building a large string by creating new string in each iteration is bad for performance as it is an O(n^2) operation. You should prefer a StringBuilder.

If you need last index just use if( i == users.size()-1)
In the example you provide you should use a StringBuilder for string concatenation. Then you only need to loop without asking anything and you can use for-each loop.
StringBuilder msg =new StringBuilder().append("---Player List, Count:").append(users.size()).append("---");
for (User user : users) {
msg.append(brln)
.append("--::").append(user.name)
.append(brln);
}

If you change your code a little, you can avoid a special case:
StringBuilder msg = new StringBuilder("---Player List, Count:" + users.size()
+ "---"); // Note a lack of brln
for (int i = 0; i < users.size(); i++) {
msg.append(brln + "--::" + users.get(i).name);
}
return msg.toString();
Ideally you should use a StringBuilder for concatenating strings in a loop, as I've done above.
(This solution works in your case, since you had a header including a line break. See other solutions for a generic way to insert string X between every occurence but the last in a loop).

you are doing it wrong. Change your line:
if((i - 1) == users.size())
by this one:
if(i == (users.size()-1))

Change your condition to
i == users.size() - 1
Why? In Java (and other languages) the first element in a list is at index 0, and the last element at N-1 (if N is the number of elements currently in the list), so users.size() - 1 is the index of the last element. For example, if there are 10 elements in users list, the last will be at index 9.
Full code:
String msg = "---Player List, Count:" + users.size() + "---" + brln;
for (int i = 0; i < users.size(); i++) {
//if i equals to the last index, do your special handling of the loop
if(i == (users.size() - 1)) {
msg += "--::" + users.get(i).name; //Do this at the last loop
break;
}
msg += "--::" + users.get(i).name + brln; // do this by default
}

Although this might not help you right now (when you don't use Java 8), all this messy code will have an end with Java 8:
// requires Java 8
String msg = users.stream().map(User::name).collect(Collectors.joining(brln));

Related

Check last array element

I've got a string array, and I should check i element and i + 1, for some coincidence, except the last element, because it allready checked by previous element.
String[] somearr = new {"first, second"};
arr[i] && arr[i+1], allready checked the last element, and when arr[i] = second I've got ArrayIndexOutOfBoundsException.
if (arr[i].equals("first") && arr[i + 1].equals("second"){
//do something;
}
My question is how not to check the last element because I allready checked it in previous?
Check if index + 1 out of bound:
if ((index + 1) < somearr.length && somearr[index].equals("first") && somearr[index + 1].equals("second")) {
// do something
}
You can try following
if(i< arr.length()-1 && arr[i].equals("first") && arr[i + 1].equals("second"))

Java - insert "-" between contiguous digits in string

I am trying to create new string by inserting "-" between contiguous numbers in a string, for e.g if the input string is "bea345ful" the output string should be like "bea3-4-5ful" but if input string is "be3u4t5ful" I don't need to insert "-" since none of the digits are contiguous.
I am able to make it work with following code but it fails when there are contiguous digits at end of string for e.g. "be3u4t5f67" in that case it throws StringIndexOutOfBoundsException which I understand is happening because my code is not handling this condition. Any suggestions how to fix it?
public static String insertDash(String str){
String result = "";
for (int i = 0; i < str.length(); i ++) {
if (Character.isDigit(str.charAt(i)) && Character.isDigit(str.charAt(i + 1))) {
result+=str.charAt(i) + "-";
} else {
result+=str.charAt(i);
}
} return result;
The stop condition of your loop should be i < str.length() - 1.
Without the change, at the last iteration, i is equal to str.length() - 1 and therefore accessing the element at index str.length() - 1 + 1 (with str.charAt(i + 1)) triggers the exception.
After the for loop, simply append the last character to result.

determine if array is heap data structure

I ve got an issue with the ArrayIndexOutofBound error when trying to determine whether data is heap following the 2i + 1/2 formula child-parent relationship. Do you know how can I resolve the issue?
for (int i = 0; i < array.length; i++)
{
if ((array[i] < array[2*i + 1]) || (array[i] < array[2*i + 2]))
{
bool = false;
....
}
}
I would suggest checking for the boundaries of the array first, and if it contains enough elements, then you can compare them:
if ((array.length >= 2*i + 2)
&& ((array[i] < array[2*i + 1]) || (array[i] < array[2*i + 2])))
{
bool = false;
....
}
Your for-loop guard allows i == array.length -1. But inside the loop, you look for element 2 * i + 2. That's 2 * array.length. That's way beyond the end of the array, and will always throw an excpetion (except when i == 0).
Change your for-loop guard to i < ((array.length / 2) - 1), so that the maximal value of 2 * i + 2 is array.length - 1. Also, ensure you test this both for arrays of even and odd length; I think the logic will work in only one case.

String index out of bounds in Jjava

What is the best way to check if a string index is in bounds? Let's say we are checking a String for index i-1 or i+1 because you cannot say != null.
Example:
for (int i = 0; i < string.length(); i++)
{
if (string.charAt(i+1) == '#' && string.charAt(i - 1) != '1')
{
}
}
Should you just check the length of the string and see if it is within it?
string.charAt(i+1) == '#'
Yes, I think you need to make sure i+1 is not greater than String length.
Example:
if( (i+1) < string.length() && (i-1) >= 0 && (yourcode))
{
}
Why not just check the length of the string?
if(myString.length() - 1 > i)
I've always modified the length (and/or start) of the loop in these cases... these are all good answers - there's no one way to do it, but this is how I would do it:
for (int i = 1; i < string.length() - 1; i++)
{
if (string.charAt(i+1) == '#' && (i != 1 || string.charAt(i - 1) != '1'))
{
}
}
EDIT: After considering all of the situations that this code entails, I wouldn't necessarily do this in this manner, but find a cleaner way to express exactly what I'm trying to accomplish
The simplest way is to change your for loop like this:
for (int i = 1; i < string.length() - 1; i++)
{
if (string.charAt(i+1) == '#' && string.charAt(i - 1) != '1')
{
}
}
Explanation:
string.charAt(i - 1) implies that you might read position i-1 of the string. Since 0 is the lowest valid value you can start the iteration with i = 1
string.charAt(i + 1) implies that you might read position i+1 of the string. Since string.length() - 1 is the highest valid value you need to end your iteration at i == string.length() - 2. Since the for-loop checks the condition before entering the loop using i < string.length() - 1 will be just right.
I would try with this code.
for (int i = 1; string!= null && string.length() >= 3 && i < string.length() - 1; i++)
//it solve the case of String == null and string too short
//it optimize the max number of cycles
{
if (string.charAt(i+1) == '#' && string.charAt(i - 1) != '1')
{
}
}

Shortening sorted list

Suppose you have a sorted List containing server names. You'd like to collapse them as tightly as possible.
Example:
abcd01c, abcd02c, abcd04c, abcd05, z1x
should become
abcd0[1-4]c,abcd05,z1x
What is the simplest algorithm to take care of something like this?
I would store all strings in a prefix map, which makes the decision of a String exists very easy, and also allows fast iteration of a subset of Strings.
Store the Strings as:
(0)abcd01c
(5) 2c,
(5) 4c,
(4) 05,
(0)z1x
The number is the count of characters which have to be taken from the previous String. This is a common implementation for dictionaries like phonebooks, where you have to store many similar Strings.
A Trie is a similar structure, as Brian Roach noticed in the comments.
I'm a little shaky on what your actual need is, but an approach to this would be in a custom Trie (Wikipedia Entry)
When you reached the point in your key where your next character isn't an alpha character, you'd know that you had a prefix. Inside that node in the Trie you could then have another map (not pointing at additional Trie nodes) that was keyed by the suffix and contained the ranges for each.
You still have the problem, however, of the specific rules around your data. If you have abcd01c as the key, is the prefix abcd or abcd0?
I think dynamic programming can help. The shortest length can be computed for all sets of first elements of given array, i.e. {1}, {1,2}, {1,2,3}... Those numbers are computed consequently, so previous ones are used to calculate the current number. If we want to calculate A[i] and A[j] is known (j < i) and numbers from given array from j+1 to i can be compressed, then A[i] equals A[j] + length of compressed data.
upd
I hardly understand how to compress if range is set for more then one symbol. So, here is a simple realization in case of one symbol.
int prevIdx = -1;
int count = 0;
for (int i = 1; i < list.Length; i++) {
bool ok = true;
if (list[i].Length == list[i - 1].Length) {
int count = 0;
for (int j = 0; j < list[i].Length; j++)
if (list[i][j] != list[i - 1][j])
curIdx = j;
count++;
}
if (count > 1)
ok = false;
}
else
ok = false;
if (ok) {
if (prevIdx == curIdx) {
count++;
}
else {
prevIdx = curIdx;
if (count > 1)
answer.Add(list[i - 1].SubString(0, prevIdx - 1) +
'[' + count.ToString() + ']' + list[i - 1].SubString(prevIdx + 1, list[i - 1].Length);
else
answer.Add(list[i - 1]);
count = 0;
}
}
else {
if (count > 1)
answer.Add(list[i - 1].SubString(0, prevIdx - 1) +
'[' + count.ToString() + ']' + list[i - 1].SubString(prevIdx + 1, list[i - 1].Length);
else
answer.Add(list[i - 1]);
prevIdx = -1;
}
}
if (count > 1)
answer.Add(list[List.Length - 1].SubString(0, prevIdx - 1) +
'[' + count.ToString() + ']' + list[i - 1].SubString(prevIdx + 1, list[List.Length - 1].Length);
else
answer.Add(list[list.Length - 1]);

Categories

Resources