修剪序列两边的算法

时间:2015-06-05 18:07:42

标签: scala

我有一个生成器,它生成不同长度的数字序列。对于序列中的特定值,我想生成一个新序列,该序列在此特定值的右侧和左侧最多具有10个元素。我尝试了以下但是它无法正常工作:

xs.dropRight(xs.size - xs.indexOf(x) - 10).take(xs.size - xs.indexOf(x) + 10)

一些例子:

Vector(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)

x = 11

Vector(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)

x = 9

Vector(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)

x = 1

Vector(1,2,3,4,5,6,7,8,9,10,11)

x = 18

Vector(8,9,10,11,12,13,14,15,16,17,18,19)

2 个答案:

答案 0 :(得分:5)

尝试选择元素间隔的方法slice

def myFun[T](value: T, xs: Seq[T], padding: Int) = {
  val idx = xs.indexOf(value)
  // padding + 1 because slice uses an exclusive upperbound
  xs.slice(idx - padding, idx + padding + 1)
}

scala>   myFun(3, 0 to 50, 10)
res2: Seq[Int] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

scala>   myFun(10, 0 to 50, 10)
res3: Seq[Int] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

答案 1 :(得分:1)

你只是把数学做错了。让我们画出各种情况的图片

.......0987654321x123                 <-- ending short
              321x1234567890.......   <-- beginning short
.......0987654321x1234567890.......   <-- lots of room
                 ^--- you want this one
                      val index = xs.indexOf(x)

现在,我们希望之前删除超过十个元素的所有内容。 Drop会忽略负面元素,因此如果开头很短则无关紧要,我们可以drop(index - 10)。现在我们的照片是

     0987654321x123                 <-- beginning clipped, end short
            321x1234567890.......   <-- beginning short
     0987654321x1234567890.......   <-- beginning clipped, end long

现在我们x的位置可能已经改变(如果我们放弃了任何东西)。如果没有,我们只需在index之后取10。如果是这样,我们需要21 - 我们保留的所有10个,加上x,再加上10个。 (如果没有多少人离开,take并不关心。)

xs.drop(index - 10).take(if (index > 10) 21 else index + 10)

我们现在已经结束了。

您可以使用slice来简化数学运算,它使用开始和结束索引。但是,没有固有的理由为什么下降/采取不起作用;你需要仔细计算。特别是,如果您在xs take中找到了indexOf(x)而未在您创建的新内容中{{1}},那么您的解决方案就会有效。 (浪费时间再次寻找它而不是使用数学,但它确实有效。)