2014-06-17 55 views
3

我需要复制列表中的每个元素。 这里是我想出了是:scala列表中的元素

List.range(1,5).map(i => List(i,i)).flatten 

其输出

List[Int] = List(1, 1, 2, 2, 3, 3, 4, 4) 

我不知道这是否是要做到这一点(它最终需要对大量的数据运行的最有效方法),因为对于每个元素,都会创建一个新列表。

(以上是上一个int范围,以保持例如简单)

任何建议?

+0

为什么您需要首先复制列表中的每个元素? – Ashalynd

+0

实际上,我需要在每个元素上应用两个不同的函数。效率问题将与重复相同。 – benroth

+0

元素的顺序是否重要? – Kigyo

回答

4

一个更普遍的解决办法是这样的:

def duplicate[T](list: List[T]): List[T] = list.flatMap(x => List[T](x, x)) 

使用不可变的集合将不会那么有效了非常大的数据集。使用可变ListBuffer一个简单的实现已经比上述速度快10倍(使用一百万个元素的列表):

def duplicate[T](list: List[T]): List[T] = { 

    val buffer = collection.mutable.ListBuffer[T]() 

    list.foreach{ x => 
     buffer += x 
     buffer += x 
    } 

    buffer.toList 
} 

这使用附加到一个ListBuffer性能的一般技术中,然后转化成不可变List最后。

+0

我明白这一点。我的问题是关于为原始列表中的每个元素创建和展开额外列表的效率。 – benroth

+0

并非如我的编辑所见。 –

+0

在处理性能时,使用辅助可变集合的一般方法是什么? – jarandaf

0

按照上述评论,对于任何给定的方法,如f1(x: Int): Intf2(x: Int): Int,考虑

(1 to 5).par.filter { x => f1(x) > f2(x) } 

其中par铸就范围到平行的收集,值得考虑的大集合。

+0

是的,这就是我为了保持示例简单 – benroth

3

你真的需要清单吗?你能更好地通过更通用?当其他集合更适合时,列表通常被过度使用。下面是这需要任何序列,并且创建了复制的项目,流的本性是懒惰流的方法,你不一定会创建并扔掉了很多小名单的内存开销:

def dupe[A](as: Seq[A]): Stream[A] = as match { 
    case Seq(h, t @ _*) => h #:: h #:: dupe(t) 
    case _ => Stream.empty 
} 

我们可以看到它懒洋洋地起作用:

scala> dupe(List(1,2,3,4)) 
res1: Stream[Int] = Stream(1, ?) 

懒洋洋不够,它工作在非常大的,甚至无限的输入:

scala> dupe(Stream.range(1, Int.MaxValue)).take(10).force 
res2: scala.collection.immutable.Stream[Int] = Stream(1, 1, 2, 2, 3, 3, 4, 4, 5, 5) 

scala> dupe(Stream.continually(1)).take(10).force 
res3: scala.collection.immutable.Stream[Int] = Stream(1, 1, 1, 1, 1, 1, 1, 1, 1, 1) 

如果你真的想要的清单:

scala> dupe(List(1,2,3,4)).toList 
res5: List[Int] = List(1, 1, 2, 2, 3, 3, 4, 4) 
+0

而忽略了'toList'在最后花费巨大。 –

+0

@LimbSoup是的,这是真的,但我预测这个答案是“也许你不需要一直列出”。 – stew

2

而另一个版本

def dupe[T](xs:List[T]):List[T] = 
    xs.foldRight(List[T]()) {(elem, acc) => elem::elem::acc} 

大概约高效的地图,但可节省超过列表一个额外的迭代压扁

1

另一种解决方案:
参数倍意味着如何很多时候你想重复列表中的每个元素

def repeatElementsInList[T](list: List[T],times: Int): List[T] = { 
     list.flatMap (x => 
     List.fill(times)(x) 
     ) 
    } 

scala> repeatElementInList(List("a",1,"b"),3) 
res6: List[Any] = List(a, a, a, 1, 1, 1, b, b, b) 
+1

请提供您的代码的解释,以便OP可以从中学习。 – EBH

相关问题