6

I am very new to Scala and the whole functional programming style. What I need to do is calculating the similarity between two Strings by comparing each letter of both words. The function will be used with words of same length.

For example "network" and "workout" would have a similarity of 1. "House" and "Mouse" would have a similarity of 4.

Here is how I would do it in a very old fashioned C# way:

int calculateCharSimilarity(string first, string second)
{
  int similarity = 0;
  for(int i = 0; i < first.lenght() && i < first.lenght(); i++)
  {
    if(first.charAt(i) == second.charAt(i))
      similarity++;
  }
  return similarity;
}

What I did in scala so far is to write a tail recursive function in order to avoid the loop:

@tailrec
private def calculateCharSimilarity(first: Seq[Char], second: Seq[Char], similarity: Int = 0): Int = {
  if(first != Nil && second != Nil)
    calculateCharSimilarity(first.tail, second.tail, if(first.head == second.head) similarity + 1 else similarity)
  else
    similarity
}

But I am not so sure if that is best practise in Scala. Isn't there any way to do it more elegant with Collection Combinators (zip, filter) for example?

1 Answer 1

10
def charSimilarity(first: String, second: String) =
  (first.view zip second).count{case (a, b) => a == b}

charSimilarity("network", "workout")
// Int = 1

charSimilarity("House", "Mouse")
// Int = 4

You could drop method view here. In this case you'll create a new collection of tuples (Char, Char) of size min(first.size, second.size). For small strings (single word) you'll get no performance issue.

Alternative implementation:

(first, second).zipped.count{case (a, b) => a == b}
Sign up to request clarification or add additional context in comments.

7 Comments

For completeness and future reference, the body of the same method in C# could be return first.Zip(second, Tuple.Create).Count(t => t.Item1 == t.Item2);, so quite similar. :)
@PatrykĆwiek: I guess first.Zip(second, (a, b) => a == b).Count(t => t) is even better (no unnecessary Tuple creations, and I just don't like ItemN and _N methods).
True and good catch! Unfortunately, C# lacks the syntactic sugar and support for tuples akin to Scala and F# and I just wanted to be as close to your solution as possible.
Thanks @senia, that is exactly what I looked for! Just to follow up - what exactly is the benefit of 'view' in this case? Is it in order to create the tuples in a lazy way? Could an '(first.iterator zip second)' do it as well? PS: thanks PatrykĆwiek and senia, I didn't use the Zip extended method in C# so far, so I'll keep that one in mind!
@AlexanderWeber: Could an '(first.iterator zip second)' do it as well?, yes, but you should use (first.iterator zip second.iterator). Iterator is mutable, view is immutable. It could lead to some strange errors, so I prefer to avoid iterators.
|

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.