组合自定义类型的2个向量以返回1个向量

时间:2016-08-23 19:27:46

标签: scala scalaz

我有一个班级:

case class Custom(label: String, num: Long)

鉴于这两个清单:

val l1 = Vector(Custom("a", 1), Custom("aa", 1))
val l2 = Vector(Custom("a", 1))

我希望获得结果列表:

val l3 = Vector(Custom("a", 2), Custom("aa", 1))

我试过像这样使用折叠:

l1.foldLeft(l2)((acc: List[Custom], el: Custom) => {
   val itemWithIndex: Option[(Custom, Int)] = acc.zipWithIndex.find(_._1.label == el.label)
   itemWithIndex match {
     case Some(x) => acc.updated(x._2, Custom(el.label, acc(x._2).num + el.num))
     case None => el :: acc
   }
})

此实现迭代累加器(l2)3次,l1迭代一次。我正在寻找更有效的解决方案。

2 个答案:

答案 0 :(得分:2)

布莱恩提出了一个很好的建议,就是简单地将这些列表合并到一起:

(l1 ++ l2)
  .groupBy(_.label)
  .map { 
    case (label, customs) => Custom(label, customs.map(_.num).sum)
  }

groupBy为我们提供了Map[String, List[Custom]],其中List[Custom]是具有相同标签的所有Custom个对象。剩下的就是总结List,并为每个标签创建一个新的Custom对象。

由于这是一个减少,它可以被制成一个Monoid:

implicit def customMonoid = new Monoid[Vector[Custom]] {
  override def append(l1: Vector[Custom], l2: => Vector[Custom]): Vector[Custom] =
    (l1 ++ l2)
      .groupBy(_.label)
      .map {
        case (a, b) => Custom(a, b.map(_.num).sum)
      }.toVector

  override def zero: Vector[Custom] = Vector.empty[Custom]
}

答案 1 :(得分:1)

 import scalaz.syntax.monoid._
  case class Custom(label: String, num: Long)
  val l1 = Vector(Custom("a", 1), Custom("aa", 1))
  val l2 = Vector(Custom("a", 1))

  def toM(v: Vector[Custom]): Map[String, Long] = {
    (v map (cus ⇒ cus.label → cus.num)).toMap
  }

  def fromM(m: Map[String, Long]): Vector[Custom] = {
    m.map{case (l , num) ⇒ Custom(l, num)}.toVector
  }

  implicit val myMonoid = new Monoid[Vector[Custom]] {
    import scalaz.std.anyVal.longInstance
    val mm = scalaz.std.map.mapMonoid[String, Long]

    override def zero: Vector[Custom] = fromM(mm.zero)

    override def append(f1: Vector[Custom], f2: ⇒ Vector[Custom]): Vector[Custom] = fromM(mm.append(toM(f1), toM(f2)))
  }



  println(l1 |+| l2) \\Vector(Custom(a,2), Custom(aa,1))

如果您想更清楚,可以将toMfromM提取到Isomorphism实例。