考虑这样一张地图:
Map("one" -> Iterable(1,2,3,4), "two" -> Iterable(3,4,5), "three" -> Iterable(1,2))
我想获得Iterable
下所有可能的元素排列列表,每个键都有一个元素。对于这个例子,这将是:
// first element of "one", first element of "two", first element of "three"
// second element of "one", second element of "two", second element of "three"
// third element of "one", third element of "two", first element of "three"
// etc.
Seq(Iterable(1,3,1), Iterable(2,4,2), Iterable(3,5,1),...)
实现这一目标的好方法是什么?
答案 0 :(得分:3)
val m = Map("one" -> Iterable(1,2,3,4), "two" -> Iterable(5,6,7), "three" -> Iterable(8,9))
如果你想要每一个组合:
for (a <- m("one"); b <- m("two"); c <- m("three")) yield Iterable(a,b,c)
如果你想让每个可迭代者一起游行,但是当最短时间被挖出时停止:
(m("one"), m("two"), m("three")).zipped.map((a,b,c) => Iterable(a,b,c))
如果你想让每个iterable环绕一下,但是当最长的一个用完时停止:
val maxlen = m.values.map(_.size).max
def icf[A](i: Iterable[A]) = Iterator.continually(i).flatMap(identity).take(maxlen).toList
(icf(m("one")), icf(m("two")), icf(m("three"))).zipped.map((a,b,c) => Iterable(a,b,c))
编辑:如果你想要任意数量的输入列表,那么你最好使用递归函数。对于笛卡尔积:
def cart[A](iia: Iterable[Iterable[A]]): List[List[A]] = {
if (iia.isEmpty) List()
else {
val h = iia.head
val t = iia.tail
if (t.isEmpty) h.map(a => List(a)).toList
else h.toList.map(a => cart(t).map(x => a :: x)).flatten
}
}
并替换zipped
您需要的内容如下:
def zipper[A](iia: Iterable[Iterable[A]]): List[List[A]] = {
def zipp(iia: Iterable[Iterator[A]], part: List[List[A]] = Nil): List[List[A]] = {
if (iia.isEmpty || !iia.forall(_.hasNext)) part
else zipp(iia, iia.map(_.next).toList :: part)
}
zipp(iia.map(_.iterator))
}
您可以使用cart(m.values)
,zipper(m.values)
和zipper(m.values.map(icf))
进行尝试。
答案 1 :(得分:2)
如果您要购买笛卡儿产品,我有一个solution for lists of lists of something。
xproduct (List (List (1, 2, 3, 4), List (3, 4, 5), List (1, 2)))
res3: List[List[_]] = List(List(1, 3, 1), List(2, 3, 1), List(3, 3, 1), List(4, 3, 1), List(1, 3, 2), List(2, 3, 2), List(3, 3, 2), List(4, 3, 2), List(1, 4, 1), List(2, 4, 1), List(3, 4, 1), List(4, 4, 1), List(1, 4, 2), List(2, 4, 2), List(3, 4, 2), List(4, 4, 2), List(1, 5, 1), List(2, 5, 1), List(3, 5, 1), List(4, 5, 1), List(1, 5, 2), List(2, 5, 2), List(3, 5, 2), List(4, 5, 2))
用Rex'm:
调用它xproduct (List (m("one").toList, m("two").toList, m("three").toList))
答案 2 :(得分:1)
看看this answer。问题是关于要合并的固定数量的列表,但是一些答案解决了一般情况。