新的迭代与另一个重复的“e.field”时代的元素?

时间:2014-01-12 00:12:18

标签: scala

我想要一个接收Iterable的函数,并返回一个带有来自初始Iterable的加权对象的新函数。

让我举个例子:

对象类(我们称之为权重)的Int值为times

class Weight(val times: Int)

最初的Iterable有四个元素:{a, b, c, d}。权重如下:

  • a.times = 3
  • b.times = 1
  • c.times = 2
  • d.times = 2

结果迭代将是= {a, a, a, b, c, c, d, d}

到目前为止,我的实施非常难看:

def weightedIteration(initial: Iterable[Wheight]): Iterable[Weight] = {
  var list: List[Weight] = Nil
  initial.foreach(weight => {
    for(_ <- 0 until weight.times)
      list :+= weight
  })
  list
}

我真正不喜欢的是var列表。我宁愿让每个元素产生所需的次数。我试图将yield语句放入for表达式;但是效果不好,因为此方法中的最后一个语句是返回foreach的{​​{1}}表达式。

在这种情况下,有没有办法使用收益率?或者从一些Collection Combinator(map)中返回一个iterable?只要我摆脱var列表,​​我不介意任何一种方式。

4 个答案:

答案 0 :(得分:7)

initial.flatMap(weight => List.fill(weight.times)(weight))

答案 1 :(得分:5)

for {
    times <- List(3, 2, 5)
    n <- (1 to times)
} yield times  

答案 2 :(得分:1)

List的构建器是ListBuffer。

当地的可变状态并没有什么难看的。

scala> case class Weight(value: String, weight: Int)
defined class Weight

scala> val ws = List(Weight("a",3),Weight("b",1),Weight("c",2))
ws: List[Weight] = List(Weight(a,3), Weight(b,1), Weight(c,2))

scala> (ListBuffer[Weight]() /: ws) { case (r, w) => 1 to w.weight foreach (_ => r += w); r }
res4: scala.collection.mutable.ListBuffer[Weight] = ListBuffer(Weight(a,3), Weight(a,3), Weight(a,3), Weight(b,1), Weight(c,2), Weight(c,2))

scala> .toList
res5: List[Weight] = List(Weight(a,3), Weight(a,3), Weight(a,3), Weight(b,1), Weight(c,2), Weight(c,2))

可选地,

scala> (List.empty[Weight] /: ws) { case (r, w) =>
     | var rr = r
     | 1 to w.weight foreach (_ => rr +:= w) ; rr }
res6: List[Weight] = List(Weight(c,2), Weight(c,2), Weight(b,1), Weight(a,3), Weight(a,3), Weight(a,3))

scala> .reverse
res7: List[Weight] = List(Weight(a,3), Weight(a,3), Weight(a,3), Weight(b,1), Weight(c,2), Weight(c,2))

值得一提

scala> for (w <- ws; _ <- 1 to w.weight) yield w.value
res8: List[String] = List(a, a, a, b, c, c)

答案 3 :(得分:0)

您可以使用为Iterables定义的地图方法def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): TraversableOnce[B],这会返回一个可以使用toList方法转换为列表的Iterable。

它可以这样使用:

val newList = initial.flatMap(weight => List.fill(weight.times)(weight)).toList