1

I have an String array, I want to see how many distinct strings there are in this array. Meaning how many string's there are, not counting repeated strings. Here is what I have:

int strings = 0;
int arrayLength = x.length;

    for (int currentNum = 1; currentNum < arrayLength; currentNum++) {
        for (int i = currentNum + 1; i < arrayLength; i++) {
            if (x[currentNum].equals(x[i])) {
               break;      
            } else {
              strings++;
        } 
    } 
    return strings;
}

But this never returns the correct amount, can anyone tell me why?

UPDATE:

Out of curiosity what If the I also wanted to check if the string was equal to other strings backwards? Then HashSets will not work.

Elgin Beloy
  • 93
  • 1
  • 6
  • Because you're incrementing `strings` every time in the outer loop and the inner loop does basically nothing. Not to mention that what you're doing is very unwieldy. A shorter way would be to put all the `Strings` in a `HashSet` and check its size. – Kayaman Oct 24 '15 at 20:23
  • Note that arrays in Java start from index **0**, and end at **length - 1**. The way you are doing it, you're bound to have an exception thrown. – RealSkeptic Oct 24 '15 at 20:25
  • Unless your array has only one element, this will never loop. Re-read how for loops work. – JB Nizet Oct 24 '15 at 20:26
  • Also no exception is thrown, re-read code. But I do see where my for loops are wrong – Elgin Beloy Oct 24 '15 at 20:35
  • Can you clarify your question? What should the answer be for `{"A", "A"}`? `0` or `1`? – Paul Boddington Oct 24 '15 at 20:36
  • The second part of the `for` statement tells when the loop should continue. That condition is `currentNum == arrayLength`. So that means: "continue looping while currentNum (which is initialized to 1) is equal to the length of the array. So that condition is false from the start, so the loop is never executed. – JB Nizet Oct 24 '15 at 20:36
  • Oh my gosh...I'm so sorry I messed up sorry. – Elgin Beloy Oct 24 '15 at 20:37
  • The answer should be one – Elgin Beloy Oct 24 '15 at 20:37
  • @ElginBeloy then you should reformulate the question. You're not trying to find strings which are not equal to any other string as you're saying. You're trying to find distinct strings, i.e. to count every string only once, whether its 1, 2, 3 or 1000 times in the array. – JB Nizet Oct 24 '15 at 20:39
  • Also Isn't the break only breaking out of the inner for loop? – Elgin Beloy Oct 24 '15 at 20:40
  • @JBNizet Adding edits now. – Elgin Beloy Oct 24 '15 at 20:41
  • You keep changing your code. Every time you do it, it makes my explanation wrong. – Paul Boddington Oct 24 '15 at 21:09

5 Answers5

4

There are 2 problems with your code. Firstly, array indices start at 0, not 1. Secondly, the break takes you to the line strings++, when you want to skip that line. Instead you want to continue the outer loop so that the line strings++ is not executed. Annoyingly you cannot use continue on its own as this applies to the inner loop. You can use a label, like this:

loop:
for (int currentNum = 0; currentNum < arrayLength; currentNum++) {
    for (int i = currentNum + 1; i < arrayLength; i++) {
        if (x[currentNum].equals(x[i])) {
            continue loop;
        }
    }
    strings++;
}
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
1

Please try with hashset.

    int strings = 0;
    int arrayLength = x.length;

    HashSet<String> unique = new HashSet<String>(Arrays.asList(x));
    return unique.size();

I have added sample code snippet. Please try this.

Siva Kumar
  • 1,983
  • 3
  • 14
  • 26
  • 1
    I take back my previous comment, now thath the OP has made it clear that he actually wanted distinct elements. Your answer is still not very good though. You should explain why a Set is a good solution, rather than provide code without any explanation. – JB Nizet Oct 24 '15 at 20:40
  • 1
    Well, the first two lines of code are useless, and it doesn't have any explanation as I just said. So it's right, but not good. It also doesn't explain the problems in the OP's code. – JB Nizet Oct 24 '15 at 20:43
  • 1
    @BalusC After reading multiple times I dont think my understanding of problem is not wrong. – Siva Kumar Oct 24 '15 at 20:43
1

Try this:

int strings = 0;
int arrayLength = x.length;

for (int currentNum = 0; currentNum < arrayLength; currentNum++) {
    ++strings;

    for (int i = 0; i < arrayLength; i++) {
        if (i != currentNum && x[currentNum].equals(x[i])) {
           --strings;
           break;      
        }
    }
} 

return strings;

This way you add 1 for the current string, then check all others (not including himself) and if you find you, you subtract 1.

lub094
  • 103
  • 7
1

If you want to check if the strings match backwards too, you could create another set (backwardsSet) with the backward strings and put it in the other set only if it's not present in the backwardsSet.

Lubo Kanev
  • 480
  • 1
  • 5
  • 12
0

If you really just want to count distinct strings then simply use this:

Arrays.stream(strings).distinct().count()

And if you want to ignore palindromes:

 final String[] strings = { "ab", "ba", "ab", "cd" };
    // I assume a and b are not null
    final BiPredicate<String, String> equal = 
        (a, b) -> a.equals(b) || new StringBuilder(a).reverse().toString().equals(b);
    final Set<String> set = new HashSet<>();
    for (final String s1 : strings)
      if (!set.stream().anyMatch(s2 -> equal.test(s1, s2)))
        set.add(s1);
    System.out.println(set.size());

If you need to process a lot of strings you could optimize this. Strings of different lengths could not be equal. Yo you could create a partition where you have subsets of strings of same size. Then process those subsets (see Collectors.groupBy(...)).

Claude Martin
  • 745
  • 6
  • 21