假设我有一个元组列表:
val xs: List[(Seq[String], Option[String])] = List(
(Seq("Scala", "Python", "Javascript"), Some("Java")),
(Seq("Wine", "Beer"), Some("Beer")),
(Seq("Dog", "Cat", "Man"), None)
)
和一个函数,如果它在字符串序列中,则返回字符串的索引:
def getIndex(s: Seq[String], e: Option[String]): Option[Int] =
if (e.isEmpty) None
else Some(s.indexOf(e.get))
现在我尝试使用xs
映射getIndex
并仅返回我找到有效索引的那些。一种方法如下:
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 :(得分: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))
答案 1 :(得分:2)
有很多方法可以做到这一点。其中之一是:
val result = xs.flatMap { tuple =>
val (seq, string) = tuple
string.map(s => (s, seq.indexOf(s))).filter(_._2 >= 0)
}
答案 2 :(得分:1)
也许这看起来更像惯用语:
#!/usr/bin/osascript
set output to "Title,Notes,Completed,Completion Date,List,Creation Date,Due Date,Modification Date,Remind Me Date,Priority\n"
tell application "Reminders"
set rs to reminders in application "Reminders"
repeat with r in rs
set output to output & "\"" & name of r & "\",\"" & body of r & "\",\"" & completed of r & "\",\"" & completion date of r & "\",\"" & name of container of r & "\",\"" & creation date of r & "\",\"" & due date of r & "\",\"" & modification date of r & "\",\"" & remind me date of r & "\",\"" & priority of r & "\"\n"
end repeat
end tell
return output
答案 3 :(得分:1)
我们可以使用collect
方法合并map
和filter
:
xs.collect { case (s, e) if e.isDefined => (e, s.indexOf(e.get)) }
.filter { case (e, i) => i > 0 }
答案 4 :(得分:0)
map
和getOrElse
可能会让事情变得更加清晰:
// 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)