【问题标题】:scala calculate number of occurences of an elementscala计算元素的出现次数
【发布时间】:2018-10-19 21:28:22
【问题描述】:

我有以下列表作为输入:

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

我想计算每个元素的出现次数而不是与每个元素相关的总和,因此想要的输出将是:

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

请知道如何实现这一点

【问题讨论】:

  • 你为什么到处使用字符串?你没有整数吗?或案例类
  • 这里如何使用案例类
  • 您似乎在寻求有关如何编写基本 scala 代码的教程。这不是合适的网站。请阅读How to ask,并发布Minimal, Complete, Verifiable Example。向我们展示您尝试了什么,哪些没有奏效。但是您的第一个任务是将输入解析为字符串和整数。
  • 尽管有val 的名字,但您的输入/输出都不是列表。如果您未绑定到现有的输入/输出数据类型,请考虑将它们从 Tuple of Strings 更改为 List of Tuples,例如 List( ("banana", 10), ("apple", 20), ... )

标签: scala reduce


【解决方案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 )
}

这本质上与其他两个答案的作用相同(查看 case e => 并且您会看到相似之处),但是在两个答案中都有修改您的输入的逻辑,以便可以对其进行聚合。

这个命令中有几件事值得解释:

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

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

【讨论】:

    【解决方案2】:

    你可以期待这样的输出

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

    【讨论】:

      【解决方案3】:

      您可以执行以下操作

      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
      

      【讨论】:

        猜你喜欢
        • 2020-02-08
        • 2012-06-11
        • 2022-11-30
        • 1970-01-01
        • 2020-06-09
        • 2020-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多