Scala - can a lambda parameter match a tuple?

前端 未结 5 1643
眼角桃花
眼角桃花 2021-02-02 05:42

So say i have some list like

val l = List((1, \"blue\"), (5, \"red\"), (2, \"green\"))

And then i want to filter one of them out, i can do some

相关标签:
5条回答
  • 2021-02-02 06:15

    There are a bunch of options:

    for (x <- l; (n,s) = x if (n != 2)) yield x
    l.collect{ case x @ (n,s) if (n != 2) => x }
    l.filter{ case (n,s) => n != 2 }
    l.unzip.zipped.map((n,s) => n != 2).zip   // Complains that zip is deprecated
    
    0 讨论(0)
  • 2021-02-02 06:15
    val m = l.filter( (n, s) => n != 2 )
    

    ... is a type mismatch because that lambda defines a

    • Function2[String,Int,Boolean] with two parameters instead of
    • Function1[(String,Int),Boolean] with one Tuple2[String,Int] as its parameter.

    You can convert between them like this:

    val m = l.filter( ((n, s) => n != 2).tupled )
    
    0 讨论(0)
  • 2021-02-02 06:25

    I've pondered the same, and came to your question today.

    I'm not very fond of the partial function approaches (anything having case) since they imply that there could be more entry points for the logic flow. At least to me, they tend to blur the intention of the code. On the other hand, I really do want to go straight to the tuple fields, like you.

    Here's a solution I drafted today. It seems to work, but I haven't tried it in production, yet.

    object unTuple {
      def apply[A, B, X](f: (A, B) => X): (Tuple2[A, B] => X) = {
        (t: Tuple2[A, B]) => f(t._1, t._2)
      }
      def apply[A, B, C, X](f: (A, B, C) => X): (Tuple3[A, B, C] => X) = {
        (t: Tuple3[A, B, C]) => f(t._1, t._2, t._3)
      }
      //...
    }
    
    val list = List( ("a",1), ("b",2) )
    val list2 = List( ("a",1,true), ("b",2,false) )
    
    list foreach unTuple( (k: String, v: Int) =>
      println(k, v)
    )
    
    list2 foreach unTuple( (k: String, v: Int, b: Boolean) =>
      println(k, v, b)
    )
    

    Output:

    (a,1)
    (b,2)
    (a,1,true)
    (b,2,false)
    

    Maybe this turns out to be useful. The unTuple object should naturally be put aside in some tool namespace.

    Addendum:

    Applied to your case:

    val m = l.filter( unTuple( (n:Int,color:String) =>
        n != 2
    ))
    
    0 讨论(0)
  • 2021-02-02 06:31

    Hmm although Kipton has a good answer. You can actually make this shorter by doing.

    val l = List((1, "blue"), (5, "red"), (2, "green"))
    val m = l.filter(_._1 != 2)
    
    0 讨论(0)
  • 2021-02-02 06:36

    This is about the closest you can get:

     val m = l.filter { case (n, s) => n != 2 }
    

    It's basically pattern matching syntax inside an anonymous PartialFunction. There are also the tupled methods in Function object and traits, but they are just a wrapper around this pattern matching expression.

    0 讨论(0)
提交回复
热议问题