【问题标题】:All possible permutations of values for such a map这种地图的所有可能的值排列
【发布时间】:2011-05-23 12:22:24
【问题描述】:

考虑这样的地图:

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),...)

什么是实现这一目标的好方法?

【问题讨论】:

  • 这不是排列。排列在所有可能的顺序中都是单个集合,例如 1、2、3; 1,3,2; 2,1,3; 2,3,1; 3,1,2; 3,2,1。您可能的意思是“转置”(第二个索引的元素优先于第一个索引)。
  • 什么定义了键的顺序,因为 Map 键没有排序?
  • @Paul 我不想订购它。考虑Iterable(1,2,3)Iterable(2,3,1)Iterable(3,1,2)Iterable(3,2,1) 是相同的。
  • 所以您想将映射中的键视为无序,将每个值迭代器中的值视为无序,将结果视为一组无序的无序值(每个映射值中的一个)?只是检查,因为您的示例是有序的(因为它是 Seq)
  • 你想要cartesian product

标签: scala collections map


【解决方案1】:
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))

如果您希望每个可迭代对象都回绕,但在最长的一个已用完时停止:

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)) 尝试这些。

【讨论】:

  • 所有这些都硬连线了要使用的键的数量。有没有一种巧妙的方法来处理包含任意数量条目的地图?
  • 太好了,谢谢。我会去自学有关笛卡尔积的知识。
【解决方案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)) 

【讨论】:

    【解决方案3】:

    看看this answer。问题是关于要组合的固定数量的列表,但一些答案解决了一般情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      相关资源
      最近更新 更多