Finding elements in a scala list and also know which predicate has been satisfied

后端 未结 3 2125
时光取名叫无心
时光取名叫无心 2021-02-20 10:39

I have the following problem in scala. I have to find the first element in al list which satisfies a predicate function with two conditions in OR. The problem is that I would li

相关标签:
3条回答
  • 2021-02-20 11:10

    I'd do this:

    Scala 2.8:

    def find2p[T](l: List[T], p1: T => Boolean, p2: T => Boolean) = 
      l.view.map(el => (el, p1(el), p2(el))).find(t => t._2 || t._3)
    

    Scala 2.7:

    def find2p[T](l: List[T], p1: T => Boolean, p2: T => Boolean) = 
      l.projection.map(el => (el, p1(el), p2(el))).find(t => t._2 || t._3)
    

    The view/projection ensures that the mapping will be done on-demand, instead of being applied to the whole list.

    0 讨论(0)
  • 2021-02-20 11:21
    def find[T](l1 : List[T], c1 : T => Boolean, c2 : T => Boolean) = ((None : Option[(String, T)]) /: l1)( (l, n) => l match {
        case x : Some[_] => l
        case x if c1(n) => Some("c1", n)
        case x if c2(n) => Some("c2", n)
        case _ => None
    })
    
    scala> find(l1, c1, c2)
    res2: Option[(String, java.lang.String)] = Some((c1,B))
    
    scala> find(l2, c1, c2)
    res3: Option[(String, java.lang.String)] = Some((c2,AA))
    

    Depending on your requirements you could have a parameter Map[T => Boolean, String] for the label strings to return: def find[T](l1 : List[T], fs : Map[T => Boolean, String]) or define your own operators.

    This will evaluate the whole list where find aborts for the first element found.

    0 讨论(0)
  • 2021-02-20 11:30

    Here's a variant on Daniel's (and Retronym's) answer(s).

    If you just want the predicate (out of a list) that succeeded, then you can use

    def findP[T](list: Iterable[T], preds: Iterable[T=>Boolean]) = {
      list.view.map( x => (x , preds.find( _(x) )) ).find( _._2.isDefined )
    }
    

    Alternatively, you could use a list of named predicates:

    def findP[T](list: Iterable[T],preds: Iterable[(T=>Boolean,String)]) = {
      list.view.map(x => (x , preds.find( _._1(x) ))).find( _._2.isDefined )
    }
    
    scala> findP(
         |   List(1,2,3,4,5,6),
         |   List( ((i:Int)=>i>4,"Fred") , ((i:Int)=>(i%6)==0,"Barney"))
         | )
    res2: Option[(Int, Option[((Int) => Boolean, String)])] =
      Some((5,Some((<function1>,Fred))))
    

    The result a little cluttered, but can be unwrapped easily enough to give exactly what you asked for:

    def findP[T](list: Iterable[T],preds: Iterable[(T=>Boolean,String)]) = {
      list.view.map(x => (x , preds.find( _._1(x) ))).find( _._2.isDefined ) match {
        case Some((i,Some((_,s)))) => Some((i,s))
        case _ => None
      }
    }
    

    (This is code for 2.8; switch "view" to "projection" for 2.7.)

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