Ruby:有类似于Enumerable#drop的东西会返回一个枚举器而不是一个数组吗?

时间:2010-02-04 13:39:31

标签: ruby enumerable

我有一些大的固定宽度文件,我需要删除标题行。

跟踪迭代器似乎不是很惯用。

# This is what I do now.
File.open(filename).each_line.with_index do |line, idx|
  if idx > 0
     ...
  end
end

# This is what I want to do but I don't need drop(1) to slurp
# the file into an array.
File.open(filename).drop(1).each_line do { |line| ... }

这是什么Ruby成语?

6 个答案:

答案 0 :(得分:7)

这是略微整洁:

File.open(fname).each_line.with_index do |line, lineno|
  next if lineno == 0
  # ...
end

io = File.open(fname)
# discard the first line
io.gets
# process the rest of the file
io.each_line {|line| ...}
io.close

答案 1 :(得分:5)

如果您不止一次需要,可以写一个Enumerator的扩展名。

class Enumerator
  def enum_drop(n)
    with_index do |val, idx|
      next if n == idx
      yield val
    end
  end
end

File.open(testfile).each_line.enum_drop(1) do |line|
  print line
end

# prints lines #1, #3, #4, …

答案 2 :(得分:2)

现在您已经得到了合理的答案,这是一种完全不同的方式来处理它。

class ProcStack
  def initialize(&default)
    @block = default
  end
  def push(&action)
    prev = @block
    @block = lambda do |*args|
      @block = prev
      action[*args]
    end
    self
  end
  def to_proc
    lambda { |*args| @block[*args] }
  end
end
#...
process_lines = ProcStack.new do |line, index|
  puts "processing line #{index} => #{line}"
end.push do |line, index|
  puts "skipping line #{index} => #{line}"
end
File.foreach(filename).each_with_index(&process_lines)

这不是惯用的,也不是第一次非常直观,但它很有趣!

答案 3 :(得分:1)

脱离我的头脑,但我相信更多的研究会有更优雅的方式

File.open( filename ).each_line.to_a[1..-1].each{ |line|... }

好的从头开始......做了一些研究,这可能会更好

File.open( filename ).each_line.with_index.drop_while{ |line,index|  index == 0 }.each{ |line, index| ... }

答案 4 :(得分:1)

我怀疑这是惯用的,但很简单。

f = File.open(filename)
f.readline
f.each_line do |x|
   #...
end

答案 5 :(得分:1)

我认为你正确地使用Enumerator和drop(1)。出于某种奇怪的原因,虽然Enumerable定义了#drop,但Enumerator却没有。这是一个有效的枚举器#drop:

  class Enumerator
    def drop(n_arg)
      n = n_arg.to_i # nil becomes zero
      raise ArgumentError, "n must be positive" unless n > 0
      Enumerator.new do |yielder|
        self.each do |val|
          if n > 0
            n -= 1
          else
            yielder << val
          end
        end
      end
    end
  end