在Scala中将两个列表合并排序

4

假设我有两个列表:

List(("a",1),("b",4),("d",5),("a",7),("b",6)) 

并且

List("a","b","c","d")

我希望能够根据第一个列表将它们分组,以便得到:

List("a" -> List(("a",1),("a",7)), "b" -> List(("b",4),("b",6)), "d" -> List(("d",5)))

什么是实现这一点的最佳方法?我知道我可以使用groupBy和针对预定值进行模式匹配,但当第二个列表不是预定的时,我有些困惑。
编辑:
我需要第二个列表中对象的副本作为处理列表的键。我可能需要按第二个列表中对象的一个参数进行分组,但仍然保留整个对象作为键...如果这有意义的话。
List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
List(("a",1,1),("b",2,3),("c",5,6),("d",6,7))

成为:

 List(("a",1,1) -> List(("a",1),("a",7)), ("b",2,3) -> List(("b",4),("b",6)), ("d",6,7) -> List(("d",5)))

对于表达不清楚,我很抱歉!

4个回答

5
根据您的编辑,使用for推导式:
for {
  key <- second
  pair <- first.groupBy(_._1).get(key)
} yield key -> pair

或者没有加糖的等价物:

second.flatMap(key => first.groupBy(_._1).get(key).map(key -> _))

这两者都会对每个键执行 groupBy 操作。如果这是一个问题,你当然可以通过略微详细的方式避免它:

val mappings = first.groupBy(_._1)
second.flatMap(key => mappings.get(key).map(key -> _))

针对您的最新编辑:如果您需要将第二个列表中的每个项转换为第一个列表中的键,有几种方法可以实现。例如,假设有:

val first = List(("a", 1), ("b", 4), ("d", 5), ("a", 7), ("b", 6))
val second = List(("a", 1, 1), ("b", 2, 3), ("c", 5, 6), ("d", 6, 7))

要么:

for {
  item @ (key, _, _) <- second
  pair <- first.groupBy(_._1).get(key)
} yield item -> pair

或者:

for {
  item <- second
  pair <- first.groupBy(_._1).get(item._1)
} yield item -> pair

按预期工作。

4
解决方案非常简单:
first groupBy(_._1) toList

结果:

List((a,List((a,1), (a,7))), (d,List((d,5))), (b,List((b,4), (b,6))))

first 是你的第一个列表(第二个列表的目的是什么)?


1

另一种方式。

val first = List(("a",1),("b",4),("d",5),("a",7),("b",6))
val second = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7))
first groupBy {k => second find {_._1 == k._1} get}

这样做不会保持顺序,而这似乎是其中一个要求。 - Travis Brown
虽然你可以随时添加 toList.sortBy{_._1._1},但我会继续自私地假设他不需要保留顺序,直到明确说明为止 :) - Kaito

-1
val a = List(("a",1),("b",4),("d",5),("a",7),("b",6))
val b = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7))
val a1 = a.groupBy{ _._1 }
b.flatMap{ x => a1.get(x._1).map{x -> _} }

或者

val a = List(("a",1),("b",4),("d",5),("a",7),("b",6))
val b = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7))
b.view.map{ x => x -> a.filter{ _._1 == x._1 } }.filter{ _._2.nonEmpty }.toList

第二种方法应该是最有效的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接