如何编写一个表达式,无论顺序如何都会产生所有可能的对?

时间:2015-04-30 08:35:53

标签: scala combinatorics

我想创建一个界面来输入类似于协方差矩阵的东西。为此,我需要创建所有空的“单元格”,其中将输入数据。但是,当然,当他已经输入B和A的协方差时,我不希望用户输入A和B的协方差。

假设我将数据点A到D作为List("A", "B", "C", "D")。然后我可以写表达式

val dataPoints = List("A", "B", "C", "D")
for(firstDataPoint <- dataPoints; secondDataPoint <- dataPoints) 
  yield (firstDataPoint, secondDataPoint)

这给了我所有可能的组合,我可以为每个组合创建一个“单元格”,但问题是两者(“A”,“B”)和(“B”,“A”)都存在。

我能想到的唯一想法是创建一个空的可变集合,循环上面代码的结果,检查相反的对是否已经在可变集合中,如果没有,则将其写入可变集合。但是这个解决方案看起来对我来说看起来不好Scala样式,而且效率也很低(为什么要创建所有值并立即丢弃几乎一半?)我也想学习在函数式编程中更好,而Scala有我这样做的工具,它不会用纯粹的功能语言。

请注意,我的实际数据点没有固有的排序,所以我不能说我扔掉secondDataPoint<firstDataPoint的所有组合。

有更聪明的方法吗?

2 个答案:

答案 0 :(得分:1)

由于您的元素没有排序,您可以通过检查列表中元素的顺序来实现(因为列表是按元素的索引排序的)。所以,只需检查索引是否不同:

val dataPoints = List("A", "B", "C", "D")
for(firstDataPoint <- dataPoints; secondDataPoint <- dataPoints) 
  if(dataPoints.indexOf(firstDataPoint) >=  dataPoints.indexOf(secondDataPoint)){
   yield (firstDataPoint, secondDataPoint)
  }
}

答案 1 :(得分:1)

@ user987339的变体删除O(N)indexOf的答案。 @ user987339,随便在你的答案中包含这个,我会删除这个,这只是对你的一个小调整。

\d+