scala 将字符串列表转换为 Map[String, List]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18520417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:37:06  来源:igfitidea点击:

Convert String list into Map[String, List]

scala

提问by blue-sky

I'm trying to convert List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")to type scala.collection.immutable.HashMap[String, java.util.List[String]]with values :

我正在尝试转换List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")scala.collection.immutable.HashMap[String, java.util.List[String]]带有值的类型:

a -> 1,2
b -> 2,4
c -> 3

So each key contains a List of its values.

所以每个键都包含其值的列表。

Here is my code so far :

到目前为止,这是我的代码:

object ConvertList extends Application {

  var details = new scala.collection.immutable.HashMap[String, java.util.List[String]]

  val strList = List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")

  //Get all values
  val getValue : Function1[String, String] = { a => a.split(",")(1) }
  val allValues : List[String] = strList map getValue

  //get unique values
  val uniqueValues = allValues.toSet[String]

  //Somehow map each unique value to a value in the original List....
  println(uniqueValues)

  println(strList.flatten)
  //userDetails += "1" -> List("a","b",


}

How can this conversion be performed ?

如何进行这种转换?

回答by Marth

strList.map(s => (s(0).toString,s(2).toString))
       .groupBy(_._1)
       .mapValues(_.map(_._2))

Output :

输出 :

Map[String,List[String]] = Map(b -> List(2, 4), a -> List(1, 2), c -> List(3))

回答by om-nom-nom

Lists wouldn't be in the same order, but generally it is quite feasible problem:

列表的顺序不会相同,但通常这是一个非常可行的问题:

// for a sake of pithiness
type M = Map[String,List[String]] 
def empty: M = Map.empty.withDefaultValue(Nil)

@annotation.tailrec
def group(xs: List[String], m: M = empty): M = xs match {
    case Nil     => m
    case h::tail => 
      val Array(k,v) = h.split(",")
      val updated = v::m(k)
      combine(tail, m + (k -> updated))
}

回答by Jens Egholm

There are already a good deal of takes, but what about something similar to what Marth proposes:

已经有很多需要,但是类似于 Marth 提议的东西呢:

import scala.collection.JavaConverters._

val strList = List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")

strList.map(_.split(',')).collect { 
  case Array(key, value) => key -> value 
}.groupBy(_._1).mapValues(_.map(_._2).asJava)

This relies heavily on functional programming and ends up with a Mapof type Map[String, java.util.List[String]], while not just taking fixed positions in the input string, but splitting at the comma (imagine having numbers over 9, requiring more than one digit).

这在很大程度上依赖于函数式编程并以 a Mapof type结束Map[String, java.util.List[String]],而不仅仅是在输入字符串中占据固定位置,而是在逗号处拆分(想象一下数字超过 9,需要多于一位)。

Also, if there are more than one value from the split, the collectmethod filters them away.

此外,如果拆分中有多个值,该collect方法会将它们过滤掉。

回答by Brian

scala> List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")
res0: List[String] = List(a,1, b,2, c,3, a,2, b,4)

scala> res0.groupBy(xs => xs.split(",")(0)).mapValues(xs => xs.flatMap(xs => xs.toCharArray.filter(_.isDigit)))
res2: scala.collection.immutable.Map[String,List[Char]] = Map(b -> List(2, 4), a -> List(1, 2), c -> List(3))

Using groupBymakes this straight forward since you want a Map. The groupBysplits each element of the Listby ,and takes the first one which is the key. That gives this: scala.collection.immutable.Map[String,List[String]] = Map(b -> List(b,2, b,4), a -> List(a,1, a,2), c -> List(c,3)). From here it is just processing to get the digits from each Listof values.

使用groupBy使得这种直线前进,因为你想要一个Map。所述groupBy分裂的每个元素List,并采取的第一个这是关键。这给出了: scala.collection.immutable.Map[String,List[String]] = Map(b -> List(b,2, b,4), a -> List(a,1, a,2), c -> List(c,3)). 从这里开始只是处理从每个List值中获取数字。

This returns a Map[String, List[Char]]. There is a little more to do if you want scala.collection.immutable.HashMap[String, java.util.List[String]]returned but that's the easy part.

这将返回一个Map[String, List[Char]]. 如果您想scala.collection.immutable.HashMap[String, java.util.List[String]]返回,还有一些事情要做,但这很容易。

回答by Xavier Guihot

Starting Scala 2.13, we can use the new groupMapmethod which (as its name suggests) is a one-pass equivalent of a groupByand a mapping over grouped items:

开始Scala 2.13,我们可以使用新的groupMap方法(顾名思义),它是对分组项目的单次传递groupBymapping 的等效:

// val strList = List("a,1" , "b,2" , "c,3" , "a,2" , "b,4")
strList.map(_.split(",")).groupMap(_(0))(_(1))
// Map("b" -> List(2, 4), "a" -> List(1, 2), "c" -> List(3))

This:

这:

  • splits each string (producing List(Array(a, 1), Array(b, 2), ...))

  • groups elements based on their first part (_(0)) (group part of groupMap)

  • maps grouped elements to their second part (_(1)) (map part of groupMap)

  • 拆分每个字符串(生产List(Array(a, 1), Array(b, 2), ...)

  • groups 元素基于它们的第一部分 ( _(0)) (Map 的组部分)

  • maps 将元素分组到它们的第二部分 ( _(1)) (组Map 的映射部分)