scala 是否有更好的函数方法来操作Map[String,List[Int]]

qnzebej0  于 2022-12-13  发布在  Scala
关注(0)|答案(3)|浏览(139)

我对scala和函数式编程还是个新手,我正在做一个项目,我有30天内的食品价格,我想对我所拥有的数据进行一些分析。
数据保存为map(string, List[Int])
我想做的是得到每件商品的最低和最高价格,我是这样做的,然后我有另一个函数,循环返回的Map并打印出来.

def f(): Map[String,List[Int]] = {
    var result= Map.empty[String, List[Int]]
    for ((k,v) <- data){
      var low = v.min
      var high = v.max
      result+= (k -> List(low,high));
    }
    result
  }

我认为这不是最实用的方法,有人能详细说明是否有一种方法可以迭代数据并返回结果,而不创建一个空的Map吗?

t40tm48m

t40tm48m1#

计算完全不依赖于键,所以没有理由在任何地方引入k,这只会分散我们的注意力,让我们偏离主要目标。

data.view.mapValues(v => (v.min, v.max)).toMap

还有,你的签名f()没有给出任何有用的信息。你怎么知道它在做什么呢?如果你删除了那个函数的主体,只给了"f()",你能明确地重建主体吗?GPT能重建主体吗?可能不行。
理想情况下,签名应该足够精确,这样您就不需要深入研究实现主体(而且您实际上也不必编写它们)。

def priceRanges(itemsToPrices: Map[String, List[Int]]): Map[String, (Int, Int)] =
  itemsToPrices.view.mapValues(v => (v.min, v.max)).toMap
62o28rlo

62o28rlo2#

有几种方法可以实现这一点。我认为其中一个关键方面是可读性,因此,虽然下面的代码可以作为一个纯粹的一行程序来完成,但我认为这可能是一个可行的、可读的解决方案:

data.map { case (k, v) =>
  k -> Seq(v.min, v.max)
}

如果你喜欢,可以随意缩短。
这也是可行的,但对于不习惯函数式编程的人来说,它的可读性可能较低。

data.map(kv => kv._1 -> Seq(kv._2.min, kv._2.max))

您可能需要考虑的另一件事是:结果类型中的List/Seq不包含两个以上的元素。您可能需要使用元组或为其创建自定义类型。

krcsximq

krcsximq3#

我喜欢人们鼓励自己使用函数式Scala而不是命令式风格,所以恭喜你。
回到您的问题,我认为解决这个问题最简单的方法是使用著名的map函数:它将一个函数作为参数,描述如何转换集合中的每个元素。在您的例子中,该函数从元组(item, values)(在您的问题中应该是(k, v))转换到一个新的类似元组,但这次只转换我们感兴趣的“prices”:

def getLowAndHighPrices(itemsWithPrices: Map[String, List[Int]]): Map[String, List[Int]] =
  itemsWithPrices.map((item, prices) => (item, List(prices.min, prices.max)))

您可以将之前的map实作解读为:对于每个值(item, prices),将其转换为元组(item, List(prices.min, prices.max)map函数从字面上描述了您想要做什么,而没有确切地告诉您要遵循什么步骤,因为map会为您处理这些操作;这是函数式编程的优点之一。
您还可以以非常“实用”的方式打印结果(忽略副作用):

// For demonstration purposes
val allItemPrices: Map[String, List[Int]] =
  Map(
    "Milk" -> List(9, 8, 7, 10),
    "Eggs" -> List(1, 3, 4, 3, 5, 2)
  )

def main(args: Array[String]): Unit =
    getLowAndHighPrices(allItemPrices).foreach((item, prices) => println(s"$item -> $prices"))

/**
 * Which prints out: 
 * Milk -> List(10, 7)
 * Eggs -> List(5, 2)
 */

在本例中,foreach的功能与map非常相似,不同之处在于foreach被设计为执行副作用,例如打印到控制台。
我希望我已经说清楚了。祝你在Scala之旅中好运!

相关问题