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?
Conclusion. As we know loops cause mutation and scala adheres to the principle of immutability, Hence recursive functions are preferred over loops in scala. So when you need loops, Use Recursion and when you need Recursion. Try using Tail Recursion.
If you heard about loops in Scala, try to forget them. Try to do without them. Instead of asking “how can I loop through this”, ask “how can I transform this”. Take this one principle to heart and you'll be ahead of many Scala programmers already.
3.1. Most problems are solved using recursion because it breaks a problem into smaller tasks until it reaches a base condition or an end condition in which the recursion stops and the total result is then collated. The use of recursion is a more functional approach to writing loops than using a for loop.
In Scala, for loop is also known as for-comprehensions. A for loop is a repetition control structure which allows us to write a loop that is executed a specific number of times. The loop enables us to perform n number of steps together in one line.
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}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With