我想要一个接收Iterable
的函数,并返回一个带有来自初始Iterable
的加权对象的新函数。
让我举个例子:
对象类(我们称之为权重)的Int
值为times
:
class Weight(val times: Int)
最初的Iterable
有四个元素:{a, b, c, d}
。权重如下:
结果迭代将是= {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列表,我不介意任何一种方式。
答案 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