Scala 如何编写一个表达式来生成所有可能的对,而不考虑顺序?

Scala 如何编写一个表达式来生成所有可能的对,而不考虑顺序?,scala,combinatorics,Scala,Combinatorics,我想制作一个界面,用于输入类似于协方差矩阵的内容。为此,我需要创建所有空的“单元格”,在其中输入数据。但当然,我不希望用户在已经输入了B和A的协方差时输入A和B的协方差 假设数据点A到D是一个列表(“A”、“B”、“C”、“D”)。然后我可以写出这个表达式 val dataPoints = List("A", "B", "C", "D") for(firstDataPoint <- dataPoints; secondDataPoint <- dataPoints) yield

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

假设数据点A到D是一个
列表(“A”、“B”、“C”、“D”)
。然后我可以写出这个表达式

val dataPoints = List("A", "B", "C", "D")
for(firstDataPoint <- dataPoints; secondDataPoint <- dataPoints) 
  yield (firstDataPoint, secondDataPoint)
val数据点=列表(“A”、“B”、“C”、“D”)

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

val dataPoints = List("A", "B", "C", "D")
for(firstDataPoint <- dataPoints; secondDataPoint <- dataPoints) 
  if(dataPoints.indexOf(firstDataPoint) >=  dataPoints.indexOf(secondDataPoint)){
   yield (firstDataPoint, secondDataPoint)
  }
}
val数据点=列表(“A”、“B”、“C”、“D”)

对于(firstDataPoint,只需使用内置的
组合
方法:

List("A", "B", "C", "D").combinations(2)
这将返回一个
迭代器
。对于大多数目的来说,它应该足够了,但您当然可以将其转换为
列表
,以查看结果:

scala> List("A", "B", "C", "D").combinations(2).toList
res1: List[List[String]] = List(List(A, B), List(A, C), List(A, D), List(B, C), List(B, D), List(C, D))
正如您所见,它也不包括相同元素的对(例如,
列表(“A”,“A”)
)。出于您的目的,这可能是可以的(因为在相关矩阵中,主对角线上的所有元素都微不足道地等于1)。但如果需要,您可以添加它们:

scala> val dataPoints = List("A", "B", "C", "D")
scala> (dataPoints.combinations(2) ++ 
        (dataPoints map (el => List(el, el)))).toList
res2: List[List[String]] = List(List(A, B), List(A, C), List(A, D), List(B, C), List(B, D), List(C, D), List(A, A), List(B, B), List(C, C), List(D, D))

@user987339答案的变体,它删除了O(N)索引。@user987339,请在您的答案中包含这个,我将删除这个,这只是对您的答案的一个小调整

val dataPoints = List("A", "B", "C", "D")
val indexedDataPoints = dataPoints zipWithIndex
for(firstDataPoint <- indexedDataPoints; secondDataPoint <- indexedDataPoints) 
  if(firstDataPoint._2) >= secondDataPoint._2)){
   yield (firstDataPoint._1, secondDataPoint._1)
  }
}
val数据点=列表(“A”、“B”、“C”、“D”)
val indexedDataPoints=数据点zipWithIndex

对于(firstDataPoint,谢谢!我很早就放弃了比较的想法,因为我使用的是一个名义比例,在考虑这些值存储在哪里之前(例如,在一个有序列表中)。现在我看到了解决方案,这在事后看来是非常明显的。你可以只对集合进行zipWithIndex,然后indexOf变成O(1).看我的answer@Paul是的。想想看,我的解决方案也是立方的,因为列表的索引是线性的。