首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自测试文件的Scala映射

来自测试文件的Scala映射
EN

Stack Overflow用户
提问于 2021-03-23 01:37:16
回答 2查看 95关注 0票数 1

希望从测试文件创建一个scala映射。下面是该文本文件的一个示例(其中有几行):

代码语言:javascript
复制
Alabama (9),Democratic:849624,Republican:1441170,Libertarian:25176,Others:7312
Alaska (3),Democratic:153778,Republican:189951,Libertarian:8897,Others:6904
Arizona (11),Democratic:1672143,Republican:1661686,Libertarian:51465,Green:1557,Others:475

我已经得到了如下的地图缓冲区:

代码语言:javascript
复制
var mapBuffer: Map[String, List[(String, Int)]] = Map()

注意,参与方的值是用冒号分隔的。

我正在尝试读取文件内容并将数据存储在映射结构中,其中文件的每一行都用来构造一个映射条目,其中日期作为关键字,元组列表作为值。结构的类型应该是Map[String,List(String,Int)]。

本质上,只是尝试从文件中创建每一行的映射,但我不能完全正确地完成。我尝试了下面的方法,但没有成功--我认为'val line‘应该是一个数组而不是一个迭代器。

代码语言:javascript
复制
val stream : InputStream = getClass.getResourceAsStream("")
      val lines: Iterator[String] = scala.io.Source.fromInputStream(stream).getLines
      var map: Map[String, List[(String, Int)]] = lines
        .map(_.split(","))
        .map(line => (line(0).toString, line(1).toList))
        .toMap
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-23 06:48:23

这似乎可以完成这项工作。(Scala 2.13.x)

代码语言:javascript
复制
val stateVotes =
  util.Using(io.Source.fromFile("votes.txt")){
    val PartyVotes = "([^:]+):(\\d+)".r
    _.getLines()
     .map(_.split(",").toList)
     .toList
     .groupMapReduce(_.head)(_.tail.collect{
          case PartyVotes(p,v) => (p,v.toInt)})(_ ++ _)
  } //file is auto-closed

//stateVotes: Try[Map[String,List[(String, Int)]]] = Success(
// Map(Alabama (9) -> List((Democratic,849624), (Republican,1441170), (Libertarian,25176), (Others,7312))
//   , Arizona (11) -> List((Democratic,1672143), (Republican,1661686), (Libertarian,51465), (Green,1557), (Others,475))
//   , Alaska (3) -> List((Democratic,153778), (Republican,189951), (Libertarian,8897), (Others,6904))))

在这种情况下,状态名称后面的数字将被保留。这是可以改变的。

票数 2
EN

Stack Overflow用户

发布于 2021-03-23 07:40:43

不,迭代器是很好的(实际上比list更好),你只需要拆分这些值来创建那些元组。

代码语言:javascript
复制
    lines
      .map(_.split(","))
      .map { case l => 
         l.head -> l.tail.toList.map(_.split(":"))
                     .collect { case Seq(a,b) => a -> b.toInt }
      }
      .toMap

在我看来,另一种更美观的选择是提前转换为map,然后使用mapValues (我个人更喜欢短lambda)。缺点是mapValues是懒惰的,所以你最终不得不执行两次.toMap来强制它:

代码语言:javascript
复制
   lines
     .map(_.split(","))
     .map { case l => l.head -> l.tail.toList }
     .toMap
     .mapValues(_.split(":"))
     .mapValues(_.collect { case Seq(a,b) => a -> b.toInt })
     .toMap
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66751109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档