在Scala中向后迭代两个(不同长度)列表

时间:2014-01-30 19:32:45

标签: list scala loops

在Scala中向后迭代两个(不同长度)列表的最有效方法是什么。

所以对于两个列表

List(a,b,c) and List(1,2)

对将是

(c,2) and (b,1)

注意:我宁愿不对每个列表做反转。

4 个答案:

答案 0 :(得分:5)

一个简单的方法是:

 List('a','b','c').reverse zip List(1,2).reverse

如果您担心效率,则反转列表为O(n)

根据List的{​​{3}},使用reverseIterator 可能会更有效率。这样你就不会像reverse那样创建一个新的列表,而是在你继续迭代时遍历它。那就是:

val it = list1.reverseIterator zip list2.reverseIterator  //returns an Iterator you can force
it.toList // List((c,2), (b,1))

答案 1 :(得分:1)

使用并行集合

def parRevZip (a: List[String], b: List[Int]) = {

  val max = Math.max(a.size, b.size)
  val n = Math.abs(a.size - b.size)

  if (a.size > b.size)
    (max to n+1 by -1).par.map { i => (a(i-1), b(i-n-1)) }
  else
    (max to n+1 by -1).par.map { i => (a(i-n-1), b(i-1)) }
}

考虑到可能不同大小的列表的不同索引值,此方法从每个列表的末尾开始提取和配对相同数量的元素。

绩效需要仔细评估;对于列表,简单的反向和压缩可以证明更简单和有效;对于大型列表,相反,这种并行方法可能会引起关注。

代码优化

def parRevZip[A,B] (a: List[A], b: List[B]) = {

  val aSize = a.size
  val bSize = b.size

  val max = Math.max(aSize, bSize)
  val n = Math.abs(aSize - bSize)

  if (aSize > bSize)
    (max-1 to n by -1).par.map { i => (a(i), b(i-n)) }
  else
    (max-1 to n by -1).par.map { i => (a(i-n), b(i)) }
}

使用非递归集合

方便的不可变集合,其中大小的计算为O(1)(或准常量)(参见Recursive collections in Scala such as List)包括例如Array。 因此,

def parRevZip[A,B] (a: Array[A], b: Array[B])

不再遵循处理清单的要求。

答案 2 :(得分:0)

我认为你的意思是:

val a = List(1, 2, 3)
val b = List(8, 9)

val result = a.reverse zip b.reverse

答案 3 :(得分:0)

这是我对这个问题的尝试。原始列表ab不重复。由于O(N)

,操作为List.size
object test extends App {
  val a = List("a", "b", "c")                     //> a  : List[String] = List(a, b, c)
  val b = List(1, 2)                              //> b  : List[Int] = List(1, 2)
  val aSize = a.size                              //> aSize  : Int = 3
  val bSize = b.size                              //> bSize  : Int = 2

  // find which is smaller and which is bigger list
  val (smaller, bigger) = if (aSize < bSize) (a, b) else (b, a)
                                                  //> smaller  : List[Any] = List(1, 2)
                                                  //| bigger  : List[Any] = List(a, b, c)

  // skip the extra entries from head of bigger list
  val truncated = bigger.drop(Math.abs(aSize - bSize))
                                                  //> truncated  : List[Any] = List(b, c)

  val result = if (a == smaller)
    smaller.zip(truncated).reverse
  else
    truncated.zip(smaller).reverse                //> result  : List[(Any, Any)] = List((c,2), (b,1))

}