scala计算元素的出现次数

问题描述 投票:0回答:3

我有以下列表作为输入:

val lisinputt=("banana  10",
          "apple   20",
          "apple   30",
          "banana   10",  
          "berry    10")

并且我想计算每个元素的出现次数而不是与每个元素相关的和值,因此所需的输出将是:

val listoutput=("banana  2 20",
          "apple 2  50",  
          "berry  1  10")

请知道如何实现这一目标

scala reduce
3个回答
1
投票

你可以做下面这样的事情

val lisinputt=("banana  10",
  "apple   20",
  "apple   30",
  "banana   10",
  "berry    10")

lisinputt.productIterator.toList
  .map(x => {val splitted = x.toString.split("\\s+"); (splitted(0), 1, splitted(1))})
  .groupBy(_._1)
  .mapValues(x => (x.map(_._2.toInt).sum, x.map(_._3.toInt).sum))
  .map(x => Array(x._1, x._2._1, x._2._2).mkString(" "))
  .foreach(println)

哪个应该给你

banana 2 20
apple 2 50
berry 1 10

1
投票

根据您的原始输入,给出的两个答案都是完全正确的。但是,我的答案是假设您的输入不限于提供的表单。

处理这个问题的另一种方法是最初将数据结构化为元组,研究元组here以获取更多信息。

对于您的示例,这将看起来像:

val = lisinputt = List(
    ("banana", 10),
    ("apple", 20),
    ("apple", 30),
    ("banana", 10),
    ("berry", 10))

然后使用下面的内容,您可以访问和聚合列表。

val aggreagatedList = lisinputt.groupBy(_._1).map {
    case (fruit, number) => ( fruit, number.size , number.map(_._2).sum )
}

这基本上与其他答案都做同样的事情(看看案例e =>并且你会看到相似之处),但是在两个答案中都有修改输入的逻辑,因此它可以被聚合。

这个命令中有一些值得解释的事情:

  1. 首先,应用于lisinputt的groupBy将按唯一参数排序
  2. _._ 1表示所有元组的第一个条目(groupBy的参数)
  3. case(fruit,member)将vars分配给元组中的第一个和第二个元素(你可以将其指定为一个变量,但这会使访问者的可读性降低
  4. =>表示每个唯一(groupBy以上指定此情况)case返回一个元组条目,其中第一个元素是名称,第二个是出现次数,第三个是对原始元组中匹配水果的所有第二个条目求和。

希望这有所帮助,我也在学习,所以如果解决方案中有错误或我对这些功能的理解,我很乐意接受更正。


0
投票

您可以预期这样的输出

val listInput=("banana  10",
  "apple   20",
  "apple   30",
  "banana   10",
  "berry    10")
val result = listInput.productIterator.toList.map(_.toString.split("\\s+")).groupBy(e=> e.apply(0)).collect{
  case e=> (e._1, e._2.size, e._2.map(_.apply(1).toInt).sum)
}
//result: scala.collection.immutable.Iterable[(String, Int, Int)] = List((banana,2,20), (apple,2,50), (berry,1,10))
© www.soinside.com 2019 - 2024. All rights reserved.