2017-04-04 174 views
3

我有一个不同数量的元素0..n元素的数组。一个例子可以是:圆形阵列切片

a = [0,1,2,3,4,5,6,7,8,9] 

在迭代过程中,我想移动一个光标的阵列中,切片出元件的最大数量。如果我到了数组的“结束”,它应在开始并从挑选再次开始:

事情是这样的:

4.times do |i| 
    a.slice(i * 3, 3) 
end 
# i = 0 => [0,1,2] 
# i = 1 => [3,4,5] 
# i = 2 => [6,7,8] 
# i = 3 => [9,0,1] 
# ... 

但是最后的输出i = 3产生[9]作为.slice没有做准确我想要的是。

回答

7

你可以使用cycle

a.cycle.each_slice(3).take(4) 
#=> [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]] 
+1

正是我想到的 - 'a.cycle.each_slice(3).take “i =#{i} =>#{a}”}',但不确定是否需要这个问题:) –

+1

@AndreyDeineko这个例子包含了预期的输出:'i = 3 => [9,0 ,1]' – Stefan

1

可能的解决方案:

4.times { |i| p a.values_at(*(i*3..i*3+2).map {|e| e % 10 }) } 
[0, 1, 2] 
[3, 4, 5] 
[6, 7, 8] 
[9, 0, 1] 

9%10 = 9,10%10 = 0,11%10 = 1。因此,你会得到所需的输出。

+0

请注意,该问题有一个'ruby'标签。 – Stefan

+0

哈哈是我的坏 –

+0

虽然同样的概念适用,不是吗? –

2

你可以使用Array#rotate,然后取前3个元素每次:

4.times.each { |i| a.rotate(i*3)[0..2] } 
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]] 
0

这可能会打破一些代码,所以要小心。

class Array 
    alias_method :old_slice, :slice 
    def slice(o, c) 
    ret = old_slice(o % size, c) 
    if ret.size != c 
     ret += old_slice(0, c - ret.size) 
    end 
    ret 
    end 
end 

a = [0,1,2,3,4,5,6,7,8,9] 

4.times do |i| 
    p a.slice(i * 3, 3) 
end 

正如Stephan指出的,最好给这个方法一个不同的名字,或者创建一个CircularArray类可能会更好。

class CircularArray < Array 
    alias_method :straight_slice, :slice 
    def slice(o, c) 
    ret = straight_slice(o % size, c) 
    if ret.size != c 
     ret += straight_slice(0, c - ret.size) 
    end 
    ret 
    end 
end 
+1

只需给_your_方法另一个名字,绝对不需要重命名内置的名称。 – Stefan