Scala 如何根据';应用';食谱中的配料

Scala 如何根据';应用';食谱中的配料,scala,functional-programming,Scala,Functional Programming,因此,我有一个汤,是妥协的一系列成分。 我需要根据我已经添加到我正在制作的汤中的一系列混合物,确定我仍然需要在汤中添加哪些成分 case class Ingredient(name: String) case class Mixture(ingredient: Ingredient, amount: Int) // ingredient required to make soup val i1 = Ingredient("water") val i2 = Ingredient("salt")

因此,我有一个汤,是妥协的一系列成分。 我需要根据我已经添加到我正在制作的汤中的一系列混合物,确定我仍然需要在汤中添加哪些成分

case class Ingredient(name: String)
case class Mixture(ingredient: Ingredient, amount: Int)

// ingredient required to make soup
val i1 = Ingredient("water")
val i2 = Ingredient("salt")
val i3 = Ingredient("sugar")

val soupRequirements = Seq(Mixture(i1, 100), Mixture(i2, 200), Mixture(i3, 50))

println(soup)


val addedIngrediants = Seq(Mixture(i1, 50), Mixture(i2, 200), Mixture(i3, 40))

def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] = ???
参考:


如何准确地以函数方式减少每个混合物的正确数量?

首先定义通过中缀运算符减少两个
混合物的方法

implicit class ReduceMixtures(a: Mixture) {
  def +(b: Mixture): Mixture =
    if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
    else a
}
注意如果
成分
s不匹配,我们如何返回
a
不变。现在我们可以使用
foldLeft

def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] = {
  addedIngredients.foldLeft(soupRequirements) { case (acc, next) => acc.map(_ + next) }
}
使用
foldLeft
顺序并不重要,但是如果
soupRequirements
addedingedintents
的顺序始终是镜像的,那么我们就可以
zip
map
像这样

def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
  (soupRequirements zip addedIngredients).map { case (a, b) => a + b }

似乎是最不适合需求的抽象

import cats.implicits._
import cats.Semigroup

implicit object mixtureSemigroup extends Semigroup[Mixture] {
  def combine(a: Mixture, b: Mixture): Mixture =
    if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
    else a
}

implicit object seqMixtureSemigroup extends Semigroup[Seq[Mixture]] {
  def combine(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
    addedIngredients.foldLeft(soupRequirements) { case (acc, next) =>
      acc.map(_ |+| next)
    }
}

soupRequirements |+| addedIngredients

首先定义通过中缀运算符减少两个
混合物的方法

implicit class ReduceMixtures(a: Mixture) {
  def +(b: Mixture): Mixture =
    if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
    else a
}
注意如果
成分
s不匹配,我们如何返回
a
不变。现在我们可以使用
foldLeft

def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] = {
  addedIngredients.foldLeft(soupRequirements) { case (acc, next) => acc.map(_ + next) }
}
使用
foldLeft
顺序并不重要,但是如果
soupRequirements
addedingedintents
的顺序始终是镜像的,那么我们就可以
zip
map
像这样

def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
  (soupRequirements zip addedIngredients).map { case (a, b) => a + b }

似乎是最不适合需求的抽象

import cats.implicits._
import cats.Semigroup

implicit object mixtureSemigroup extends Semigroup[Mixture] {
  def combine(a: Mixture, b: Mixture): Mixture =
    if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
    else a
}

implicit object seqMixtureSemigroup extends Semigroup[Seq[Mixture]] {
  def combine(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
    addedIngredients.foldLeft(soupRequirements) { case (acc, next) =>
      acc.map(_ |+| next)
    }
}

soupRequirements |+| addedIngredients

谢谢假设有一种情况,在ReduceMixtures中,我想去除混合物。我有没有办法把一些/没有纳入逻辑?“如果数量低于0。”Blankman考虑<代码>(SousiQueQue++添加成分)过滤器(>数量>0)可以在折叠中使用一些/选项吗?我希望能够在折叠过程中从累积过程中完全删除一个项目,这是可能的吗?谢谢。假设有一种情况,在ReduceMixtures中,我想去除混合物。我有没有办法把一些/没有纳入逻辑?“如果数量低于0。”Blankman考虑<代码>(SousiQueQue++添加成分)过滤器(>数量>0)可以在折叠中使用一些/选项吗?我希望能够在折叠过程中完全从累积过程中移除一个项目,这是可能的吗?