# Ruby 如何仅用 each 实现 each_slice 的功能？

shaunli · 2015年03月07日 · 最后由 zyjloveher 回复于 2015年03月09日 · 3065 次阅读

``````sequence = (1..16)
buffer = []
count = 0
sequence.each do |e|
buffer << e
if buffer.size >= 4
p buffer
buffer = []
end
end
``````

``````sequence = (1..15)
buffer = []
count = 0
sequence.each do |e|
buffer << e
if buffer.size >= 4
p buffer
buffer = []
end
end
# 输出
# [1, 2, 3, 4]
# [5, 6, 7, 8]
# [9, 10, 11, 12]
``````

``````module Enumerable
def i_each_slice(n, &block)
raise "invalid slice size" if n <= 0

i, ary = 0, []

each do |a|
ary << a
i += 1
if i >= n
yield ary
i, ary = 0, []
end
end

yield ary if i > 0
end
end

(1..10).i_each_slice(3) { |a| p a }

# 输出
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
``````

#2 楼 @chiangdi 谢谢~比我的好多了:P

``````module Enumerable
def i_each_slice(n)
raise "invalid slice size" if n <= 0

result, i = [], 1

self.each do |ele|
index = (i / n.to_f).ceil
result[index].nil? ? result[index] = [ele] : result[index] << ele
i += 1
end

result[1..-1].each { |ele| yield ele }
end
end

['a', 'b', 'c', 'd', 'e', 1, 2, 3, 4, 5].i_each_slice(3) { |i| p i }
# =>
# ["a", "b", "c"]
# ["d", "e", 1]
# [2, 3, 4]
# [5]
``````

@blacktulip 的解法估计会吓退不少 ruby 初学者 这个不过是个入门级的题，我补充个杀鸡刀版吧

``````i = 0
(1..16).to_a.each do |n|
i += 1
print i % 4 == 0 ? "#{n}\n" : "#{n},"
end
``````
``````(0..3).each do |a|
arr = []
(1..4).each do |b|
arr << a * 4 + b
end
puts arr.to_s
end
``````

#7 楼 @lhy20062008 想法一致

``````(1..16).to_a.each_with_index { |n, i| print "#{n}#{(i+1)%4==0 ? "\n" : ","}" }
``````

Only use each here:

``````(array = (1..16).to_a).each { |n| print "#{n}#{(array.index(n)+1)%4==0 ? "\n" : ","}" }
``````