Teja Kantamneni
Teja Kantamneni

Reputation: 17482

What is Scala way of finding whether all the elements of an Array has same length?

I am new to Scala and but very old to Java and had some understanding working with FP languages like "Haskell".

Here I am wondering how to implement this using Scala. There is a list of elements in an array all of them are strings and I just want to know if there is a way I can do this in Scala in a FP way. Here is my current version which works...

def checkLength(vals: Array[String]): Boolean = {
  var len = -1
  for(x <- conts){
    if(len < 0)
      len = x.length()
    else{
      if (x.length() != len)
        return false
      else
        len = x.length()
    }
  }
  return true;
}

And I am pretty sure there is a better way of doing this in Scala/FP...

Upvotes: 11

Views: 10431

Answers (7)

Israel Unterman
Israel Unterman

Reputation: 13520

list.groupBy{_.length}.size == 1

You convert the list into a map of groups of equal length strings. If all the strings have the same length, then the map will hold only one such group.

The nice thing with this solution is that you don't need to know anything about the length of the strings, and don't need to comapre them to, say, the first string. It works well on an empty string, in which case it returns false (if that's what you want..)

Upvotes: 2

Duncan McGregor
Duncan McGregor

Reputation: 18177

Just my €0.02

def allElementsEval[T, U](f: T => U)(xs: Iterable[T]) =
  if (xs.isEmpty) true
  else {
    val first = f(xs.head)
    xs forall { f(_) == first }
  }

This works with any Iterable, evaluates f the minimum number of times possible, and while the block can't be curried, the type inferencer can infer the block parameter type.

  "allElementsEval" should "return true for an empty Iterable" in {
    allElementsEval(List[String]()){ x => x.size } should be (true)
  }
  it should "eval the function at each item" in {
    allElementsEval(List("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(List("aa", "bb", "ccc")) { x => x.size } should be (false)
  }
  it should "work on Vector and Array as well" in {
    allElementsEval(Vector("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Vector("aa", "bb", "ccc")) { x => x.size } should be (false)
    allElementsEval(Array("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Array("aa", "bb", "ccc")) { x => x.size } should be (false)
  }

It's just a shame that head :: tail pattern matching fails so insidiously for Iterables.

Upvotes: 0

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297295

Since everyone seems to be so creative, I'll be creative too. :-)

def checkLength(vals: Array[String]): Boolean = vals.map(_.length).removeDuplicates.size <= 1

Mind you, removeDuplicates will likely be named distinct on Scala 2.8.

Upvotes: 7

Germ&#225;n
Germ&#225;n

Reputation: 4565

Here's another approach:

def check(list:List[String]) = list.foldLeft(true)(_ && list.head.length == _.length)

Upvotes: 1

Rex Kerr
Rex Kerr

Reputation: 167921

If you know that your lists are always non-empty, a straight forall works well. If you don't, it's easy to add that in:

list match {
  case x :: rest => rest forall (_.size == x.size)
  case _ => true
}

Now lists of length zero return true instead of throwing exceptions.

Upvotes: 2

sepp2k
sepp2k

Reputation: 370445

list.forall( str => str.size == list(0).size )

Edit: Here's a definition that's as general as possilbe and also allows to check whether a property other than length is the same for all elements:

def allElementsTheSame[T,U](f: T => U)(list: Seq[T]) = {
    val first: Option[U] = list.headOption.map( f(_) )
    list.forall( f(_) == first.get ) //safe to use get here!
}

type HasSize = { val size: Int }
val checkLength = allElementsTheSame((x: HasSize) => x.size)_

checkLength(Array( "123", "456") )

checkLength(List( List(1,2), List(3,4) ))

Upvotes: 21

Dario
Dario

Reputation: 49228

Tip: Use forall to determine whether all elements in the collection do satisfy a certain predicate (e.g. equality of length).

Upvotes: 3

Related Questions