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
Convert String list into Map[String, List]
提问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方法(顾名思义),它是对分组项目的单次传递groupBy和mapping 的等效:
// 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 的映射部分)

