假设我的textFile = "a b c a b"
中有一行,并且我希望输出为= (a,b) (a,c) (a,a) (a,b) (b,c) (b,a) (b,b) (c,a) (c,b) (a,b)
。
到目前为止,我所做的是使用Scala的组合定义,但并没有出现重复的情况。
val combinations = textFile.flatMap { line =>
line.split("[\\s*$&#/\"'\\,.:;?!\\[\\](){}<>~\\-_]+")
.combinations(2).toList
.toSeq
.map{ case arr => arr(0) -> arr(1) }
}
这样做,我得到的输出为:
(a,a)
(a,b)
(a,c)
(b,b)
(b,c)
还有其他获取我想要的输出的方法,因为我认为组合在这里不起作用?
答案 0 :(得分:3)
拆分输入,将其转换为列表,使用tails
和for
理解:
val input = "a b c a b".split(" ").toList
val result = for (h :: t <- input.tails; x <- t) yield (h, x)
结果如下:
result foreach println
打印
(a,b)
(a,c)
(a,a)
(a,b)
(b,c)
(b,a)
(b,b)
(c,a)
(c,b)
(a,b)
...或者只使用嵌套的while
循环和两个显式索引i
和j
到数组中...
答案 1 :(得分:2)
我认为没有内置功能可以做到这一点,所以我相信您必须手动进行操作:
val items = line.split("[\\s*$&#/\"'\\,.:;?!\\[\\](){}<>~\\-_]+").toList
val pairs = for {
first :: rest <- items.tails.filter(_.nonEmpty)
second <- rest
} yield (first, second)
pairs.toList
tails
方法返回序列尾部的迭代器。对于您的示例,items.tails.filter(_.nonEmpty)
返回具有以下列表的迭代器:
List(a, b, c, a, b)
List(b, c, a, b)
List(c, a, b)
List(a, b)
List(b)
然后,将每个列表分为first
元素和具有rest
模式匹配的first :: rest
,并将first
元素与每个元素配对rest
。
答案 2 :(得分:2)
已定义combinations
方法来删除重复项,因此您不能将其用于解决方案。
有一个简单的递归解决方案:
def combos(letters: List[String]): List[(String, String)] =
letters match {
case Nil =>
Nil
case c :: tail =>
tail.map(d => (c, d)) ::: combos(tail)
}
这不是尾递归,因此它可能会变慢并占用大量内存,因此,如果您更关心性能而不是清晰度,那么这里是尾递归版本:
def combos(letters: List[String]) = {
@tailrec
def loop(letters: List[String], res: List[(String, String)]): List[(String, String)] =
letters match {
case Nil =>
res
case c :: tail =>
loop(tail, res ::: tail.map(d => (c, d)))
}
loop(letters, List.empty[(String, String)])
}
答案 3 :(得分:1)
以防万一,如果您正在寻找不同的方式:
val myList = "a b c a b".split(" ").zipWithIndex
for (x <- myList; y <- myList if x._2 < y._2 ) yield (x._1, y._1)