从斯卡拉阵列中删除每个第N个元素
我的要求是从斯卡拉阵列中删除每个第N个元素(请注意每个第N个元素)。我写了下面的方法来完成这项工作。因为,我是斯卡拉新手,无法避免Java宿醉。是否有更简单或更有效的替代方案?从斯卡拉阵列中删除每个第N个元素
def DropNthItem(a: Array[String], n: Int): Array[String] = {
val in = a.indices.filter(_ % n != 0)
val ab: ArrayBuffer[String] = ArrayBuffer()
for (i <- in)
ab += a(i-1)
return ab.toArray
}
这将使
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.zipWithIndex.filter(_._2 % n != 0).map(_._1)
您可以分两步功能使用zipWithIndex
得到与他们的指数tupled元素的数组做到这一点,然后collect
构建由只具有不0 = i % n
索引元素的新数组。
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] =
arr.zipWithIndex.collect { case (a, i) if (i + 1) % n != 0 => a }
我会添加'arr.toIterator。 ... .toArray'以避免创建另一个阵列 –
你确定吗?这实际上似乎让它变慢了。 –
这样的事情呢?
arr.grouped(n).flatMap(_.take(n-1)).toArray
我喜欢这样的事情;
def dropEvery[A](arr: Seq[A], n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
// example: dropEvery(1 to 100, 3)
// res0: Seq[Int] = List(1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 100)
这是有效的,因为它需要在阵列上单次通过,并从它移除每第n个元素 - 我相信这是容易看到的。 第一个案例与idx == n - 1
匹配,并忽略该索引处的元素,并通过acc
并将计数重置为0
以用于下一个元素。 如果第一种情况不匹配,这增加了该元素添加到acc
结束并递增1
既然你愿意摆脱了Java 解酒的,你可能想计数使用隐班一个非常好的方式来使用:
implicit class MoreFuncs[A](arr: Seq[A]) {
def dropEvery(n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
}
// example: (1 to 100 dropEvery 1) == Nil (: true)
任何人都在意解释为什么这是downvoted? – Ashesh
如果你正在寻找性能(因为你使用的是ArrayBuffer
),你不妨用var
跟踪指数,手动增加它,并使用if
进行检查以过滤掉n多个索引的值。
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
var i = 0
for(a <- arr) {
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
如果我们使用while循环遍历原始数组作为迭代器,它会更快。
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
val it = arr.iterator
var i = 0
while(it.hasNext) {
val a = it.next
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
你也可能想看看这个http://stackoverflow.com/questions/39105121/how-to-remove-every-nth-element-from-the-scala-list – Shankar