我正在寻找一种方法来应用List中的每个元素及其在Scala中的连续元素,而无需编写嵌套的for循环。基本上我正在寻找一个允许我执行以下操作的List理解:
让
A = {a, b, c, d}
然后A' = {ab, ac, ad, bc, bd, cd}
我考虑过使用map
例如A.map(x => ...)
,但我无法弄清楚语句的其余部分是什么样的。
希望这一切都有道理。任何帮助将不胜感激。
答案 0 :(得分:6)
这对于递归评估来说似乎很自然。因为它将第一个元素添加到列表的其余部分,然后使用应用于列表其余部分的相同内容。
def pairs(xs: List[Char]): List[String] = xs match {
case Nil | _ :: Nil => Nil
case y :: ys => ys.map(z => s"$y$z") ::: pairs(ys)
}
pairs(a) //> res0: List[String] = List(ab, ac, ad, bc, bd, cd)
尾递归
def pairs2(xs: List[Char], acc:List[String]): List[String] = xs match {
case Nil | _ :: Nil => acc.reverse
case y :: ys => pairs2(ys, ys.foldLeft(acc){(acc, z) => s"$y$z"::acc})
}
pairs2(a, Nil) //> res0: List[String] = List(ab, ac, ad, bc, bd, cd)
或者,如果你真的想要理解:
val res = for {(x::xs) <- a.tails
y <- xs
}
yield s"$x$y"
(返回一个迭代器,所以强制其评估)
res.toList //> res1: List[String] = List(ab, ac, ad, bc, bd, cd)
这表明另一种变体,来自贬低
a.tails.collect{case(x::xs) => xs.map(y=>s"$x$y")}.flatten.toList
//> res2: List[String] = List(ab, ac, ad, bc, bd, cd)
答案 1 :(得分:2)
记住在Scala中我们所拥有的是“for-comprehension”而不是Java意义上的“for-loop”,这种结构不像Java那样“嵌套”。具体来说,它看起来像:
// For a list of items of some type 'A':
val items: List[A] = ???
// and some suitable combining function (which might be inlined if simple enough):
def fn(i1: A, i2: A): A = ???
// an example for-comprehension that will achieve the output you describe:
for {
x <- items.zipWithIndex
y <- items.zipWithIndex
z <- List(fn(x._1, y._1)) if (x._2 < y._2)
} yield z
对我来说似乎足够干净。这可以解释为:
items.zipWithIndex.flatMap( x =>
items.zipWithIndex.flatMap( y =>
List(fn(x._1, y._1)).withFilter( z => x._2 < y._2 ).map( z => z ) ) )
虽然你特别要求的“列表理解”的内容更多,但对我来说似乎不那么清楚了!
答案 2 :(得分:1)
如果你正在组合Strings,你可以做这样的事情。
scala> List("a","b","c","d").combinations(2).map(s => s.head+s.last).toList
res5: List[String] = List(ab, ac, ad, bc, bd, cd)
但是你把它称为&#34;一种应用每个元素的方法&#34;所以也许你的意思是别的?如果是这样,也许这种方法可以让你开始。