我正在尝试学习Scala(2.10)。在本练习中,我有一个案例类:
case class Entry(name: String, version: String) { }
我有两个这样的对象序列,按名称属性排序:
S1 = E1, E3, E4
S2 = F1, F2, F4
我想构建一个新序列:
S3 = (E1, F1), (None, F2), (E3, None), (E4, F4)
按名称属性对其进行配对,最好不必在每个列表上多次迭代。
我对这个问题的所有解决方案都变得非常迫切(例如,有条件地增加两个整数并使用.get())。我希望某种善良的灵魂可以提出更具功能性的方法。
答案 0 :(得分:4)
您的意思是version
属性,从示例来看?
您可以使用列表和递归:
def pair(s1: List[Entry], s2: List[Entry]): List[(Option[Entry], Option[Entry])] =
(s1, s2) match {
case (Entry(_, v1) :: _, Entry(_, v2) :: _) if v1 == v2 =>
(Some(s1.head), Some(s2.head)) :: pair(s1.tail, s2.tail)
case (Entry(_, v1) :: s1t, Entry(_, v2) :: s2t) =>
if (v1 < v2) (Some(s1.head), None) :: pair(s1.tail, s2)
else (None, Some(s2.head)) :: pair(s1, s2.tail)
case (Nil, s2) => s2.map(entry => (None, Some(entry))
case (s1, Nil) => s1.map(entry => (Some(entry), None)
}
基本上,你进入列表比较他们的头部,如果版本相同,则采取两个头,或者只采用较小的头部。然后递归地对列表的尾部执行相同的操作。如果其中一个列表为空,则只需将另一个列表的其余元素映射为None
和条目对。
答案 1 :(得分:0)
如果我理解正确,EX
表示name="E"
和version="X"
,您希望将相同版本的内容配对。这是我的解决方案,不幸的是需要平时,所以如果效率很重要,请不要使用它......
val versions = (S1 ++ S2) map { _.version } groupBy (identity) keys
val sortedVersions = versions.toSeq.sorted
sortedVersions map { ver => (S1 find { _.version==ver }, S2 find { _.version==ver }) }
或者如果您事先知道可能的版本是什么,只需制作一个序列并执行最后一行。
Seq("1", "2", "3", "4") map { ver => (S1 find { _.version==ver }, S2 find { _.version==ver }) }
结果:
ArrayBuffer((Some(Entry(E,1)),Some(Entry(F,1))), (None,Some(Entry(F,2))), (Some(Entry(E,3)),None), (Some(Entry(E,4)),Some(Entry(F,4))))
请注意,我(None, F2)
代替(None, Some(F2))
,而None
与Some
配对似乎更加一致。
BTW,case class(...)
就足够了,您无需在其后面添加空括号{ }
。
答案 2 :(得分:0)
我无法在我的ipad上显示详细信息;)但是如果数字中没有很多间隙,您可以扫描每个列表,通过构建新列表或向量在空白处插入Nones(向量更快)使用像axel22这样的递归算法显示,然后将集合压缩在一起。