选自《七周七语言》的 Ruby 部分:
有一个数组,包含 16 个数字。仅用 each 方法打印数组中的内容,一次打印 4 个数字。然后,用可枚举模块的 each_slice 方法重做一遍
我想问如何仅用 each 实现 each_slice 的功能?我的想法很丑陋:
sequence = (1..16)
buffer = []
count = 0
sequence.each do |e|
  buffer << e
  if buffer.size >= 4
    p buffer
    buffer = []
  end
end
有没有更好的方法呢?
楼主这个是有问题的,如果把 16 改成 15:
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]
期待大神们更优雅的解法。
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
          (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" : ","}" }