Alexander Weber
Alexander Weber

Reputation: 799

Avoiding loops in Scala

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?

Upvotes: 6

Views: 1372

Answers (1)

senia
senia

Reputation: 38045

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}

Upvotes: 10

Related Questions