给定列表中每个第n项的列表

时间:2014-08-10 09:57:07

标签: scala scala-collections

这是我在Scala中解决的一个简单练习:给定一个列表l会返回一个新列表,其中包含n-th的每个l元素。如果n > l.size返回空列表。

def skip(l: List[Int], n: Int) = 
  Range(1, l.size/n + 1).map(i => l.take(i * n).last).toList

我的解决方案(见上文)似乎有效但我正在寻找smth。简单。你会如何简化它?

6 个答案:

答案 0 :(得分:15)

有点简单:

scala> val l = (1 to 10).toList
l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// n == 3

scala> l.drop(2).grouped(3).map(_.head).toList
res0: List[Int] = List(3, 6, 9)

// n > l.length

scala> l.drop(11).grouped(12).map(_.head).toList
res1: List[Int] = List()

(toList只是为了强制评估iteratot)

使用无限列表:

Stream.from(1).drop(2).grouped(3).map(_.head).take(4).toList
res2: List[Int] = List(3, 6, 9, 12)

答案 1 :(得分:8)

scala> def skip[A](l:List[A], n:Int) = 
         l.zipWithIndex.collect {case (e,i) if ((i+1) % n) == 0 => e} // (i+1) because zipWithIndex is 0-based
skip: [A](l: List[A], n: Int)List[A]

scala> val l = (1 to 10).toList
l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> skip(l,3)
res2: List[Int] = List(3, 6, 9)

scala> skip(l,11)
res3: List[Int] = List()

答案 2 :(得分:4)

更具可读性,循环大小为O(l.length/n)

def skip(l: List[Int], n: Int) = {
  require(n > 0)
  for (step <- Range(start = n - 1, end = l.length, step = n))
    yield l(step)
}

答案 3 :(得分:1)

向左折叠O(n)

def skip(xs: List[Int], n: Int) = {
  xs.foldLeft((List[Int](), n)){ case ((acc, counter), x) =>
      if(counter==1)
        (x+:acc,n)
      else
        (acc, counter-1)
  }
  ._1
  .reverse
}

scala > skip(List(1,2,3,4,5,6,7,8,9,10), 3)

Tailrec不太可读的方法O(n)

import scala.annotation.tailrec

def skipTR(xs: List[Int], n: Int) = {
  @tailrec
  def go(ys: List[Int], acc: List[Int], counter: Int): List[Int] = ys match {
    case k::ks=>
      if(counter==1)
        go(ks, k+:acc , n)
      else
        go(ks, acc, counter-1)
    case Nil => acc
  }
  go(xs, List(), n).reverse

}
skipTR(List(1,2,3,4,5,6,7,8,9,10), 3)

答案 4 :(得分:1)

基于filter索引的两种方法,如下所示,

implicit class RichList[A](val list: List[A]) extends AnyVal {

  def nthA(n: Int) = n match {
    case 0 => List()
    case _ => (1 to a.size).filter( _ % n == 0).map { i => list(i-1)}
  }

  def nthB(n: Int) = n match {
    case 0 => List()
    case _ => list.zip(Stream.from(1)).filter(_._2 % n == 0).unzip._1
  }
}

等等给定列表

val a = ('a' to 'z').toList

我们有那个

a.nthA(5)
res: List(e, j, o, t, y)

a.nthA(123)
res: List()

a.nthA(0)
res: List()

<强>更新

使用List.tabulate如下,

implicit class RichList[A](val list: List[A]) extends AnyVal {
  def nthC(n: Int) = n match {
    case 0 => List()
    case n => List.tabulate(list.size) {i => 
                if ((i+1) % n == 0) Some(list(i)) 
                else None }.flatten
  }
}

答案 5 :(得分:0)

如果你不介意迭代器,你可以省略toList:

 scala> def skip[A](l:List[A], n:Int) =
      l.grouped(n).filter(_.length==n).map(_.last).toList
 skip: [A](l: List[A], n: Int)List[A]

 scala> skip (l,3)
 res6: List[Int] = List(3, 6, 9)