在Scala中加入两个长度不等的列表

时间:2016-03-23 18:09:20

标签: scala scala-collections

我有2个名单:

val list_1 = List((1, 11), (2, 12), (3, 13), (4, 14))
val list_2 = List((1, 111), (2, 122), (3, 133), (4, 144), (1, 123), (2, 234))

我想将第二个列表中的键替换为第一个列表的值,从而产生一个新的列表,如下所示:

List ((11, 111), (12, 122), (13, 133), (14, 144), (11, 123), (12, 234))

这是我的尝试:

object UniqueTest {
  def main(args: Array[String]){
     val l_1 = List((1, 11), (2, 12), (3, 13), (4, 14))
     val l_2 = List((1, 111), (2,122), (3, 133), (4, 144), (1, 123), (2, 234))
     val l_3 = l_2.map(x => (f(x._1, l_1), x._2))
     print(l_3)

  }
  def f(i: Int, list: List[(Int, Int)]): Int = {
    for(pair <- list){
      if(i == pair._1){
        return pair._2
      }
    }
    return 0
  }
}

这导致:

((11, 111), (12, 122), (13, 133), (14, 144), (11, 123), (12, 234))

上面的程序是一个很好的方法吗? Scala中是否有内置函数来处理这种需求,或者采用其他方式来进行这种操作?

3 个答案:

答案 0 :(得分:4)

你唯一真正过度复杂的就是这一行:

val l_3 = l_2.map(x => (f(x._1, l_1), x._2))

您的f函数使用命令式样式循环遍历列表以查找密钥。任何时候你发现自己这样做,这是一个很好的迹象,你想要的是map。通过每次爆炸计算复杂性时执行for循环:地图将允许您在O(1)中获取给定键的相应值。使用映射,您首先将列表(键值对)转换为明确支持键值对关系的数据结构。

因此,你应该做的第一件事是建立你的地图。 Scala使用toMap提供了一种非常简单的方法:

val map_1 = list_1.toMap

然后这只是'映射'的问题:

val result = list_2.map { case (key, value) => map_1.getOrElse(key, 0), value) }

这会将list_2中的每个案例与第一个值(key)匹配到map_1中的键,检索该值(或默认0)并将put作为键值元组中的第一个值。

答案 1 :(得分:2)

你可以这样做:

val map = l_1.toMap         // transform l_1 to a Map[Int, Int]
// for each (a, b) in l_2, retrieve the new value v of a and return (v, b)
val res = l_2.map { case (a, b) => (map.getOrElse(a, 0), b) }

答案 2 :(得分:0)

最惯用的方式是将它们拉到一起,然后根据您的需要进行转换:

(list_1 zip list_2) map { case ((k1, v1), (k2, v2)) => (v1, v2) }