How do I use the forall loop to check if all rows have the same number of columns in a Vector in Scala?

114 Views Asked by At

So I have a generic vector: 1:vec: Vector[Vector[T]] Now I wanna use the require and forall to check if the length of each row is the same. This is how far I've gotten: 2:require(vec.forall(row => data(row).length == ???) So essentially I wanna make sure that each row has same number of columns, I don't wanna use 3:data(row + 1).length since I could probably use a for loop in that case. Can anyone give a tip on how to resolve code 2?

2

There are 2 best solutions below

0
Levi Ramsey On

If all the rows must have the same length, you can compare each row with any of the others.

if (vec.size < 2) true  // vacuous
else {
  val firstLength = data(vec.head).length
  vec.forall(row => data(row).length == firstLength)
}

Strictly speaking, the first comparison in the forall will always be true, but Vector.tail is probably more work than performing the comparison; if data(row).length is particularly expensive, making it

vec.tail.forall(...)

might be worth it.

(If instead of a Vector, we were dealing with a List, tail is most definitely cheaper than data(row).length, though other cautions around using List may apply)

0
iris On

Consider a 3x4 vector of vectors such as for instance

val xs = Vector.tabulate(3) { _ => Vector.tabulate(4) { _ =>  1 }}

namely,

Vector(Vector(1, 1, 1, 1), 
       Vector(1, 1, 1, 1), 
       Vector(1, 1, 1, 1))

Collect the size for each nested vector,

val s = xs.map {_.size}
// Vector(4, 4, 4)

Now we can compare consecutive sizes with Vector.forall by pairing them with

s.zip(s.drop(1))
// Vector((4,4), (4,4))

where the first pair corresponds to the first and second vector sizes, and the second pair to the second and third vector sizes; thus

s.zip(s.drop(1)).forall { case(a,b) => a == b }
// true

With this approach we can define other predicates in Vector.forall, such as monotonically increasing pairs,

val xs = Vector(Vector(1), Vector(1,2), Vector(1,2,3))

val s = xs.map {_.size}
// Vector(1, 2, 3)

s.zip(s.drop(1))
// Vector((1,2), (2,3))

s.zip(s.drop(1)).forall { case(a,b) => a == b }
// false

s.zip(s.drop(1)).forall { case(a,b) => a < b }
// true