2

The following code compiles and does what I require. It iterates through an int-based multidimensional array (called nums), and searches for all occurances of the value 1. This program's output is shown below. There are three things to note:

  • Regarding the "outer for" loop statement, I have used Java's comma operator to declare two additional variables.
  • Also regarding this "outer for", I've used another comma operator in the "iteration section", to reset one of these additional variables.
  • Regarding the "inner for", I've used another comma operator in the "iteration section" to increment this additional variable.
int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};

for (int i=0, elsSearched=0, foundCount=0; i < nums.length; i++, elsSearched=0) {
    for (int j=0; j < nums[i].length; j++, elsSearched++) {
        if (nums[i][j] == 1) {
            foundCount++;
        }
    }
    System.out.println("Searched " + elsSearched + 
" elements, and found \'number one\' a total of " + foundCount + " times..");
}       

Program output:

Array search results

Could this code be written more effeciently/elegantly?

My other query is about Java's "for each" loop. I tried rewritting the code above using the "for each" loop with the comma operator, but the code wouldn't compile. I quickly came to the obvious conclusion, but would the "for each" loop be better if the comma operator could be used with it, or would that just introduce "distracting clutter"?

2
  • I don't think you can do it more efficiently, as you have to look at each element at least once to tell if it is a one ;) Commented Dec 8, 2013 at 11:57
  • Also see this answer regarding the efficiency of for-each loops vs for loops. Commented Dec 8, 2013 at 12:06

3 Answers 3

2

Edit: Be aware that foundCount is the total number of elements found up until now, as it is never reset to zero. Was this intended?

Don't you agree that this code is easier to read and more concise? (Note: efficiency is the same as your code)

int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};

int foundCount = 0; 
for(int[] inner : nums){
    for(int i : inner){
        if (i == 1){
            foundCount++;
        }
    }
    System.out.println("Searched " + inner.length + 
                " elements, and found \'number one\' a total of " + foundCount + " times..");
}

Output:

Searched 3 elements, and found 'number one' a total of 2 times..
Searched 2 elements, and found 'number one' a total of 2 times..
Searched 1 elements, and found 'number one' a total of 2 times..
Searched 3 elements, and found 'number one' a total of 2 times..
Searched 3 elements, and found 'number one' a total of 4 times..
Sign up to request clarification or add additional context in comments.

1 Comment

Excellent, thanks. Yes, the 'foundCount' functionality was as intended, and yes, I do agree with you that your code is both easier to read, and more concise. Thank you.
1

First, you probably shouldn't optimize something until you've proven it's a significant contributor to your program runtime. That being said, why not try this instead...

int foundCount = 0;
int totalCount = 0;
for (final int[] i : nums) { // foreach int[] in nums
  for (final int v : i) {    // foreach value v in the int[] from nums
    switch (v) {             // switch on a constant int...
    case 1:                  // The value we seek.
      ++foundCount;          // Add to the foundCount, and fall through!
    default:
      ++totalCount;
    }
  }
}
System.out.println("Searched a total of " + totalCount + 
            " elements and found '#1' a total of " + foundCount);

3 Comments

I'm curious, why the final keyword? Is there a performance advantage or is it just a safety net?
Yes. There are optimizations possible when things are immutable (that the runtime and compiler can optimize) and also with using the switch versus the if.
Not sure about a jump table for just 3 targets, but I agree on the final. Too bad elegance and efficiency are not always the same.
0

If you have performance issues you can try to use binary search (if your array is always sorted) on the sub arrays.

int valueToSearch = 1;

for(int[] inner : nums){

     int foundIndex = Arrays.binarySearch(inner, valueToSearch);

      if (foundIndex >= 0){
          foundCount ++;
       }

}

So you will get a performance of O(n * log(n) ) instead of O(n^2).

I guess you have to do some benchmarks. But the most important thing is to know how your input looks like. Than you can find the best algorithm for it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.