用另一个范围对范围进行采样

时间:2014-08-07 16:10:59

标签: scala scala-collections

我想"示例" Range使用另一个Range。例如:

def sample(in: Range, by: Range): Range = ???

// note: Range equals broken!
assert(sample(3 to 10     , 1 to 2     ).toVector == (4 to 5     ).toVector)
assert(sample(3 to 10     , 1 to 4 by 2).toVector == (4 to 6 by 2).toVector)
assert(sample(3 to 10 by 2, 1 to 2     ).toVector == (5 to 7 by 2).toVector)
assert(sample(3 to 10 by 2, 1 to 4 by 2).toVector == (5 to 9 by 4).toVector)

如何定义sample方法?

2 个答案:

答案 0 :(得分:0)

这是一次尝试。我还没有测试过所有可能的组合。为简单起见,by参数的起点必须大于或等于零,并且是一个正步骤。

def sample(in: Range, by: Range): Range = {
  val drop  = by.start
  val stepM = by.step
  require(drop >= 0 && stepM > 0)
  val in1 = in.drop(drop)
  val in2 = if (stepM == 1) 
    in1 
  else if (in1.isInclusive)  // copy-method is protected :(
    new Range.Inclusive(start = in1.start, end = in1.end, step = in1.step*stepM)
  else
    new Range          (start = in1.start, end = in1.end, step = in1.step*stepM)
  in2.take(by.size)
}

答案 1 :(得分:0)

通过将sample返回类型更改为IndexedSeq[Int],获得了这个简单的解决方案,

def sample(in: Range, by: Range): IndexedSeq[Int] = {
  in intersect (in.start+by.start to in.start+by.end by by.step)
}

inby之间的交叉点的任务与in.start一起移位。

对于相应重构的断言,这两个传递,

assert(sample(3 to 10     , 1 to 2     ) == (4 to 5     ))
assert(sample(3 to 10     , 1 to 4 by 2) == (4 to 6 by 2))

这两个失败了,

assert(sample(3 to 10 by 2, 1 to 2     ) == (5 to 7 by 2)) // intersect at 5 only
assert(sample(3 to 10 by 2, 1 to 4 by 2) == (5 to 9 by 4)) // empty intersect