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.

12
  • 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. Commented Oct 24, 2015 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. Commented Oct 24, 2015 at 20:25
  • Unless your array has only one element, this will never loop. Re-read how for loops work. Commented Oct 24, 2015 at 20:26
  • Also no exception is thrown, re-read code. But I do see where my for loops are wrong Commented Oct 24, 2015 at 20:35
  • Can you clarify your question? What should the answer be for {"A", "A"}? 0 or 1? Commented Oct 24, 2015 at 20:36

5 Answers 5

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++;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I did this, it still returns the wrong value please help.
Sorry, just. Help now.
@ElginBeloy Give me an example of an array which gives the wrong answer.
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.

3 Comments

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.
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.
@BalusC After reading multiple times I dont think my understanding of problem is not wrong.
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.

Comments

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.

Comments

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(...)).

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.