简体   繁体   English

Map 并在 Scala 中折叠一个集合

[英]Map and fold a collection in Scala

I have a fold which iterates through elements, dependently modifies them one by one and at the same time modifies their parent.我有一个fold元素,它遍历元素,依赖地一个一个地修改它们,同时修改它们的父级。

Currently I replace the elements in their parent one by one in the fold , they are just few and it is not a real performance issue, but I wonder if there is perhaps a nicer way to express this.目前我在fold中一个一个地替换其父元素中的元素,它们很少,这不是真正的性能问题,但我想知道是否有更好的方式来表达这一点。

case class Behavior(x: Int) {
  def simulate(s: Entity): Behavior = copy(x = x + (if (s.alternate) 2 else 1))
}

case class Entity(alternate: Boolean, behaviors: List[Behavior]) {
  def replaceBehavior(o: Behavior, n: Behavior): Entity = {
    copy(behaviors = behaviors.patch(behaviors.indexOf(o), Seq(n), 1))
  }
  def toggleAlternate: Entity = copy(alternate = !alternate)

  def simulate: Entity = {
    behaviors.foldLeft(this) { (e, b) =>
      e.replaceBehavior(b, b.simulate(e)).toggleAlternate
    }    
  }
}

val entity = Entity(false, List(Behavior(10), Behavior(20), Behavior(30)))

entity.simulate

Is there some operation or perhaps some clever use of scan or something like that which would allow me to perform foldLeft and map dependent of the foldLeft result in one step?是否有一些操作或一些巧妙地使用scan或类似的东西可以让我在一步中执行foldLeftmap依赖于foldLeft结果? (I would prefer vanilla standard Scala library, but using functional frameworks is possible too). (我更喜欢香草标准 Scala 库,但也可以使用功能框架)。

Folds ( fold , foldLeft , foldRight , ...) usually turn some Collection[A] into B .折叠( foldfoldLeftfoldRight ,...)通常将一些Collection[A]变成B

You could map over A before folding result to B - foldMap maps A => B and assumed existence of Monoid[B] (this is available in Cats in Foldable typeclass), so you would perform transformation Collection[A] --using f--> Collection[B] --using Monoid[B]--> B (code can optimize it to perform things in one step using eg foldLeft internally).在将结果折叠到B之前,您可以在A上 map - foldMap映射A => B并假设存在Monoid[B] (这在Foldable类型类中的 Cats 中可用),因此您将执行转换Collection[A] --using f--> Collection[B] --using Monoid[B]--> B (代码可以优化它以在一个步骤中使用例如foldLeft在内部执行操作)。

Reversing the order of operations - we fold and then we map - is in general impossible because there is nothing that can let us assume that after fold step we will end up with something that is a Functor .颠倒操作的顺序——我们fold然后我们map通常是不可能的,因为没有什么可以让我们假设在fold步骤之后我们最终会得到一个Functor的东西。

Depending on your specific use case we might try using foldMap to achieve your goal.根据您的具体用例,我们可能会尝试使用foldMap来实现您的目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM