我需要连续号码添加到新阵列,如果它是不连续的号码,只值添加到一个新的数组:连续的分组编号在数组
old_array = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29]
我想这结果:
new_array = [
[1,2,3],
[5],
[7,8,9]
[20,21]
[23],
[29]
]
是否有更简单的方法来做到这一点
我需要连续号码添加到新阵列,如果它是不连续的号码,只值添加到一个新的数组:连续的分组编号在数组
old_array = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29]
我想这结果:
new_array = [
[1,2,3],
[5],
[7,8,9]
[20,21]
[23],
[29]
]
是否有更简单的方法来做到这一点
这是RDoc给出(略有修改),官方的回答:
种actual = old_array.first
old_array.slice_before do
|e|
expected, actual = actual.next, e
expected != actual
end.to_a
如何在ruby 1.8.7中编写代码? – bluexuemei
Ruby 1.8.7不再被维护,并且包含几个已知的安全漏洞。你应该避免使用它。 –
很好的答案,谢谢 – bluexuemei
一对夫妇的其他方式:
old_array = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29]
#1
a, b = [], []
enum = old_array.each
loop do
b << enum.next
unless enum.peek.eql?(b.last.succ)
a << b
b = []
end
end
a << b if b.any?
a #=> [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
#2
def pull_range(arr)
b = arr.take_while.with_index { |e,i| e-i == arr.first }
[b, arr[b.size..-1]]
end
b, l = [], a
while l.any?
f, l = pull_range(l)
b << f
end
b #=> [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
可能不应该这样说,但那先生是一件艺术品! –
感谢恭维,@约翰。 (约翰指的是#1;后来我加了#2)。 –
你也可以做这样的:
old_array=[1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29]
new_array=[]
tmp=[]
prev=nil
for i in old_array.each
if i != old_array[0]
if i - prev == 1
tmp << i
else
new_array << tmp
tmp=[i]
end
if i == old_array[-1]
new_array << tmp
break
end
prev=i
else
prev=i
tmp << i
end
end
使用chunk
你可以这样做:
old_array.chunk([old_array[0],old_array[0]]) do |item, block_data|
if item > block_data[1]+1
block_data[0] = item
end
block_data[1] = item
block_data[0]
end.map { |_, i| i }
# => [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
一些答案似乎不必要的长时间,就可以做到这一点非常紧凑的方式:
arr = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29]
arr.inject([]) { |a,e| (a[-1] && e == a[-1][-1] + 1) ? a[-1] << e : a << [e]; a }
# [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
另外,先从第一个元素,以摆脱a[-1]
条件(需要的情况下,当a[-1]
将nil
,因为a
是空的):
arr[1..-1].inject([[arr[0]]]) { |a,e| e == a[-1][-1] + 1 ? a[-1] << e : a << [e]; a }
# [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
Enumerable#inject迭代可枚举的所有元素,建立其与给定的对象开始的结果值。我在我的解决方案中分别给它一个空数组或第一个数组,其中第一个数值包含在数组中。然后我简单地检查我们迭代的输入数组的下一个元素是否等于结果数组中最后一个数组的最后一个值加上1(即,如果它是下一个连续元素)。如果是,我将它追加到最后一个列表中。否则,我用它中的那个元素开始一个新的列表,并将它追加到结果数组中。
很好的答案,谢谢 – bluexuemei
使用哈希你可以这样做:
counter = 0
groups = {}
old_array.each_with_index do |e, i|
groups[counter] ||= []
groups[counter].push old_array[i]
counter += 1 unless old_array.include? e.next
end
new_array = groups.keys.map { |i| groups[i] }
有点晚了这个晚会,但是:
old_array.slice_when { |prev, curr| curr != prev.next }.to_a
# => [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
+1。 'slice_when'被[添加](https://bugs.ruby-lang.org/issues/9826)到ruby版本'2.2',并且提供了比这些旧的答案更优雅的解决方案。 –
这是学校?你有什么尝试?你在寻求帮助还是为了我们为你做? – DutGRIFF
'new_array'的条件? –
相关问题:http://stackoverflow.com/q/3728660/38765 –