0

Say I have

val l1 = List(1,2,3,4)
val l2 = List(True,False,False,True)

I want to filter elements of l1 that corresponds to True elements in l2

I have done the following:

type Predicate[T] = T => Boolean
def filterXbasedOnY[A, B](X: List[A], Y: List[B], p: Predicate[B]): List[A] = {
    {
      for {i <- 0 until Y.size if p(Y(i))} yield X(i)
    }.toList
}

which is working fine by calling:

val result = filterXbasedOnY(l1, l2, (b:Boolean) => b)

but is this the best way to accomplish this?

2
  • 1
    l1.zip(l2).filter(_._2).map(_._1) Commented Feb 23, 2018 at 13:15
  • 1
    l1.zip(l2).collect{case (x,true) => x} Commented Feb 24, 2018 at 0:42

3 Answers 3

2
List(1, 2, 3, 4).zip(List(true, false, false, true)).filter(_._2).map(_._1)

As suggested by @C4stor, if the idea is to broaden the usage of the filtering to different types, I think we can reduce the complexity (I use toMatch: B in the following to simplify, but the Predicate can still be used):

def filter[A, B](l1: List[A], l2: List[B], toMatch: B): List[A] = {
  l1.zip(l2).filter(_._2 == toMatch).map(_._1)
}

The pipeline would thus be O(n) while keeping working with List objects. Otherwise, calling p(Y(i)) on a List n times would be O(n2).

As specified by @C4stor, and as it's already the case with your solution, it handles l1 being shorter than l2.

filter(List("1", "2", "3"), List("True", "False", "True", "False"), "True") // List(1, 3)
Sign up to request clarification or add additional context in comments.

Comments

0

I don't know if it's the best way, but it's at least a good way :

  • It's easy to read, and explicit
  • It handles l2 not being booleans, it can easily be fixed to handle correctly X being a smaller size than Y
  • It's well contained and easy to test

None of the proposed one liners have those desirable properties, so, kudos to you, well done ! You're solution is actually, in my opinion, on the way to be the prod ready version of the proposed one liners.

Btw, may I suggest to you the codereview stackexchange for codereview style questions ?

2 Comments

In defence of one-liners: 1.1) upper case letters for variable names? 1.2) it's roughly three times as long as the zip-map. 1.3) Being three times as long as zip-map, it invokes the impression as if it does something more sophisticated that a simple zip-map, which is even more confusing. 2) zip works fine if one of the arguments is shorter, the code in Q would crash if X.size < Y.size 3.1) If the code doesn't have to be written, there is also no need to test it. Both zip+map have been thorougly tested. 3.2) It takes O(n^2) time for a blatantly linear operation = not well done.
I didn't want to enter a code review style, which isn't appropriate for SO (I verged on closing the question tbh because of that). I just wanted to point that having this kind of function is in fact not a bad thing, and has multiple advantages. I would still not have wrote it this exact way tbh, but I can see the usefulness. But once again, it's a code review question at this point, so I don't wanna err on this side on this site ^^
0

For syntax might make it more readable, and the use of a filterFunction means that l2 can be whatever type it needs to be.

for( (l1,l2) <- (list1 zip list2) if (filterFunction(l2))) yield l1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.