1

我正在尝试学习 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())。我希望某个善良的灵魂可以提出一种更实用的方法。

4

3 回答 3

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和条目。

于 2013-02-02T17:48:50.530 回答
0

我无法在我的 ipad 上显示详细信息;),但如果数字中没有太多空白,您可以扫描每个列表,通过使用像 axel22 这样的递归算法显示,然后将集合压缩在一起。

于 2013-02-03T02:57:39.863 回答
0

如果我理解正确,EX则表示name="E"and 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))这里,因为配对似乎更一致NoneSome

顺便说一句,case class(...)就足够了,您不需要{ }在其后添加空括号。

于 2013-02-02T17:47:22.733 回答