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

时间:2013-08-29 20:30:21

标签: scala

我正在尝试将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

因此每个键都包含其值列表。

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

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",


}

如何执行此转换?

5 个答案:

答案 0 :(得分:13)

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

输出:

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

答案 1 :(得分:3)

列表的顺序不一样,但一般来说这是非常可行的问题:

// 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))
}

答案 2 :(得分:3)

已经有很多需要,但是类似于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)

这很大程度上依赖于函数式编程,最终得到Map类型Map[String, java.util.List[String]],而不只是在输入字符串中占用固定位置,而是在逗号处分割(想象数字超过9,需要多个数字。)

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

答案 3 :(得分:1)

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))

使用groupBy可以直接进行,因为您需要MapgroupByList的每个元素拆分为,,并取第一个作为关键字的元素。这给了这个: 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值的数字。

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

答案 4 :(得分:0)

Scala 2.13开始,我们可以使用新的groupMap方法(顾名思义),它等效于groupBymap分组的项目:

// 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))

此:

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

  • group的元素基于其第一部分(_(0))(地图的组部分)

  • map的元素分组到第二部分(_(1))(组 Map 的映射部分)