2017-03-21 19 views
1

はのは、私はタプルのリストを持っているとしましょう文字列:最善の方法

def getIndex(s: Seq[String], e: Option[String]): Option[Int] = 
    if (e.isEmpty) None 
    else Some(s.indexOf(e.get)) 

は今、私はgetIndexxsの上にマッピングし、私だけが有効なインデックスを見つけたものを返すようにしようとしています。これを行う1つの方法は、次のとおりです。

xs.map{case (s, e) => { 
    val ii = getIndex(s, e) // returns an Option 
    ii match { // unpack the option 
    case Some(idx) => (e, idx) 
    case None => (e, -1) // give None entries a placeholder with -1 
    } 
}}.filter(_._2 != -1) // filter out invalid entries 

この方法は、私にとっては非常に冗長であり、厄介です。 flatMapは、インデックスの代わりにタプルを返すので、ここでは機能しません。これを行う慣用方法は何ですか?

+0

そのうちの一つがこれですflatMap。あなたのSome()ケースの戻りリスト((e、idx))とNoneの場合はNilを返す –

答えて

0

mapgetOrElse物事が少し明確になるかもしれない:

// use map you will get Some(-1) if the element doesn't exist or None if the element is None 
xs.map{case (s, e) => (e, e.map(s.indexOf(_)))}. 

// check if the index is positive and use getOrElse to return false if it's None 
    filter{case (e, idx) => idx.map(_ >= 0).getOrElse(false)} 

// res16: List[(Option[String], Option[Int])] = List((Some(Beer),Some(1))) 

または:

xs.map{ case (s, e) => (e, e.map(s.indexOf).getOrElse(-1)) }.filter(_._2 != -1) 
// res17: List[(Option[String], Int)] = List((Some(Beer),1) 
2

for comprehensionはこれを達成するための一つの方法である:

scala> val xs: List[(Seq[String], Option[String])] = List(
    (Seq("Scala", "Python", "Javascript"), Some("Java")), 
    (Seq("Wine", "Beer"), Some("Beer")), 
    (Seq("Dog", "Cat", "Man"), None) 
) 
xs: List[(Seq[String], Option[String])] = List((List(Scala, Python, Javascript),Some(Java)), (List(Wine, Beer),Some(Beer)), (List(Dog, Cat, Man),None)) 

scala> def getIndex(seq: Seq[String], e: Option[String]): Option[Int] = 
    e.map(seq.indexOf(_)).filter(_ != -1) // notice we're doing the filter here 
getIndex: getIndex[](val seq: Seq[String],val e: Option[String]) => Option[Int] 

scala> for { 
    (seq, string) <- xs 
    index <- getIndex(seq, string) 
    s <- string 
} yield (s, index) 
res0: List[(String, Int)] = List((Beer,1)) 
2

たくさんありますこれを行う方法の

val result = xs.flatMap { tuple => 
    val (seq, string) = tuple 
    string.map(s => (s, seq.indexOf(s))).filter(_._2 >= 0) 
} 
1

たぶん、これはもう少し慣用的になります:

val two = xs.filter {case (s, e) => e.isDefined} 
    .map {case (s, e) => (e, s.indexOf(e.get)) } 
    .filter {case (e, i) => i > 0} 
1

我々はmapfilterを組み合わせることcollectメソッドを使用することができます。

あなたが使用することができます
xs.collect { case (s, e) if e.isDefined => (e, s.indexOf(e.get)) } 
    .filter { case (e, i) => i > 0 } 
+0

これで終了します: 'xs.collect {case(s、Some(e))s.contains(e)=>( s、s.indexOf(e))} ' – jwvh