Question

I could not find standard string-function in Java to find matching letters in 2 strings.

Do you know how to make the below code smaller/refactor it using some standard functions?

I only made simplest function: compare every letter of first string to every letter of second string.

public static void compare_letters(String name1, String name2) {
  int equal_letters = 0 ;
  for(int i = 0 ; i < name1.length() ; i++) {
    String current_letter  = name1.substring(i,i+1);

    for(int j = 0 ; j < name2.length() ; j++) {
      if(current_letter.equals(name2.substring(j,j+1)))
        equal_letters++ ;
    }
  }
  System.out.println("num of equal letters " + equal_letters) ;
}

public static void main(String args[]) {
  String n1 = "abc";
  String n2 = "bcd";
  compare_letters(n1,n2);
}

How do i refactor it to make it smaller - I m sure there must be some elegant way to do this! This is so common procedure - there must be elegant way to do that!

Was it helpful?

Solution

Your code could be simplified a bit:

public static void compare_letters(String name1, String name2) {
    int equal_letters = 0 ;

    for( char c1 : name1.toCharArray() )
        for( char c2 : name2.toCharArray() )
            if( c1 == c2 ) equal_letters++;

    System.out.println("num of equal letters " + equal_letters);
}

But note that this way of comparing will double-count repeated letters, e.g. comparing "aa" to "aa" will return four, because each a in one string will be compared to each a in the other.

If you want to count common letters without double-counting repetitions, you'd need to do something like

public static void compare_letters(String name1, String name2) {

    // Declare a couple of sets: sets don't allow duplicate elements.
    Set<Character> letters1 = new HashSet<Character>();
    Set<Character> letters2 = new HashSet<Character>();

    // Populate the sets with the letters from the strings.
    for( char c : name1.toCharArray() ) letters1.add(c);
    for( char c : name2.toCharArray() ) letters2.add(c);

    // remove anything that isn't in letters2 from letters1
    letters1.retainAll(letters2);

    // letters1 is now the set of letters that appear in both names.
    // Its size is the number of common letters.
    System.out.println("num of equal letters " + letters1.size(););
}

OTHER TIPS

This should be enough

    int count = 0;
    for (char c : n1.toCharArray()) {
        if (n2.contains(String.valueOf(c))) {
            count++;
        }
    }

I suppose the most elegant solution would be to use Guava's intersection method:

public static void compare_letters(String name1, String name2) {
    Set<Character> set1= new HashSet<Character>();
    for(char c : name1.toCharArray()) {
        set1.add(c);
    }

    Set<Character> set2 = new HashSet<Character>();
    for(char c : name1.toCharArray()) {
        set2.add(c);
    }

    System.out.println(Sets.intersection(set1, set2));
}

Well the original code would give 4 if comparing "aa" to "aa". The code with Set#retainAll would however give 1 which might not be correct as well. Following code will give 2:

char[] letters1 = name1.toCharArray();
char[] letters2 = name2.toCharArray();

Arrays.sort(letters1);
Arrays.sort(letters2);

int index1 = 0;
int index2 = 0;
int sameLetters = 0;
while ((index1 < letters1.length) && (index2 < letters2.length)) {
  switch (Integer.signum(Character.compare(letters1[index1], letters2[index2])))
  {
    case -1: // Letter from name1 before letter from name2
      ++index1;
      break;
    case 0: // Same letters in name1 and name2
      ++index1; ++index2;
      ++sameLetters;
      break;
    case 1: // Letter from name1 after letter from name2
      ++index2;
      break;
  }
}
System.out.println("Same letters: " + sameLetters);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top