【问题标题】:Convert List[(Int,String)] into List[Int] in scala在 scala 中将 List[(Int,String)] 转换为 List[Int]
【发布时间】:2018-06-02 13:58:36
【问题描述】:

我的目标是将文本(索引,行)中的每个单词映射到包含该单词出现的每一行的索引的列表。我设法编写了一个函数,该函数返回分配给索引的所有单词的列表.

下面的函数应该完成剩下的工作(将索引列表映射到每个单词):

def mapIndicesToWords(l:List[(Int,String)]):Map[String,List[Int]] = ???

如果我这样做:

l.groupBy(x => x._2)

它返回一个Map[String, List[(Int,String)]。现在我只想将值更改为键入List[Int]。 我想过使用.mapValues(...) 并以某种方式折叠列表,但我是 scala 新手,不知道正确的方法。

那么如何转换列表呢?

【问题讨论】:

  • 转换List[(Int,String)] into List[Int] 只是在做一个.map(_._1)
  • @RameshMaharjan 非常感谢
  • 你解决了吗?
  • Cleaner tuple groupBy的可能重复
  • @RameshMaharjan 是的 l.groupBy(x => x._2).mapValues[List[Int]](f => f.map(_._1)) 效果很好

标签: scala functional-programming


【解决方案1】:

您也可以使用 foldLeft,您只需指定累加器(在您的情况下为 Map[String, List[Int]]),它将作为结果返回,并在其中编写一些逻辑。这是我的实现。

def mapIndicesToWords(l:List[(Int,String)]): Map[String,List[Int]] =
  l.foldLeft(Map[String, List[Int]]())((map, entry) =>
    map.get(entry._2) match {
      case Some(list) => map + (entry._2 -> (entry._1 :: list))
      case None => map + (entry._2 -> List(entry._1))
    }
  )

但是使用 foldLeft,列表中的元素会以相反的顺序排列,因此您可以使用 foldRight。只需将 foldLeft 更改为 foldRight 并将输入参数 (map, entry) 更改为 (entry, map)

请注意,foldRight 的运行速度要慢 2 倍。使用方法 reverse list 和 foldLeft 实现。

【讨论】:

  • 根据source codefoldRight是通过foldLeft实现的,它们都不是递归的(尾或其他)。
  • 我知道所有的方法都是用命令式实现的,但我不知道foldRight是用reverse.foldLeft实现的。所以,谢谢你的澄清!
【解决方案2】:
scala> val myMap: Map[String,List[(Int, String)]]  = Map("a" -> List((1,"line1"), (2, "line")))
myMap: Map[String,List[(Int, String)]] = Map(a -> List((1,line1), (2,line)))

scala> myMap.mapValues(lst => lst.map(pair => pair._1))
res0: scala.collection.immutable.Map[String,List[Int]] = Map(a -> List(1, 2))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多