Jus12
Jus12

Reputation: 18034

arbitrary size tuple with first element type fixed

Say I have two lists

val L1 = List[(Int, Int)]((1,1), (2,2))
val L2 = List[(Int, Int, Int)]((1,1,1), (2,2,2))

Now I want to make a function func that takes in an Int value i and all items from both lists where the first element matches i. One way is

def func(i:Int) = {
  L1.collect.collect{case any if any._1 != i => any}
  L2.collect.collect{case any if any._1 != i => any}
}

considering that the two lines are so similar, it would be nice if code can be shortened. I am thinnking of some way where I could pass L1 (and L2) as a parameter to func. The function should not know in advance how many elements the tuple will have, just that the first element is Int.

Is this possible?

[EDIT: I think the question was not clear enough. My apologies.]

Here is what I want to do. I would like to do this on more than two lists, say n, by calling func several times, once for each list.

  L1 = L1.collect.collect{case any if any._1 != i => any}
  L2 = L2.collect.collect{case any if any._1 != i => any}
  ...
  Ln = Ln.collect.collect{case any if any._1 != i => any}

where each L1, L2, ... Ln are lists of tuples with first element Int

[EDIT2]

In the above, L1 could be list of (Int, String), L2 could be of (Int, Int, Int), etc. The only guarantee is that the first element is Int.

Upvotes: 0

Views: 738

Answers (2)

Kevin Wright
Kevin Wright

Reputation: 49705

Any Tuple (or, indeed, any case class) is a Product, so you can use the product iterator as a way to handle tuples of indeterminate size:

val x = (1,1,1,1)
x.productIterator forall {_ == 1} //returns true

as Product is a common supertype for the elements of both lists, you can simply concatenate them and filter:

val list1 = List((1,1), (2,2))
val list2 = List((1,1,1), (2,2,2))

(list1 ::: list2) filter {_.productIterator forall {_ == 1}}
//returns List[Product with Serializable] = List((1,1), (1,1,1))

UPDATE

To filter just a single list on the first element of contained products:

val list1 = List((1,1), (2,2))
list1 filter {_.productIterator.next() == 1}

Upvotes: 2

Luigi Plinge
Luigi Plinge

Reputation: 51109

  def func(i:Int, lst: List[Product]) = {
    lst.filter(_.productElement(0) == i)
  }

Edited as per your edit & Dan's comment above.

Upvotes: 6

Related Questions