Ruby:是否有类似 Enumerable#drop 的东西返回枚举器而不是数组?

发布于 2024-08-20 10:03:19 字数 361 浏览 7 评论 0原文

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

跟踪迭代器似乎不太惯用。

# 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 的习惯用法是什么?

I have some big fixed-width files and I need to drop the header line.

Keeping track of an iterator doesn't seem very idiomatic.

# 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| ... }

What's the Ruby idiom for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

尘曦 2024-08-27 10:03:19

稍微更简洁:

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

This is slightly neater:

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

or

io = File.open(fname)
# discard the first line
io.gets
# process the rest of the file
io.each_line {|line| ...}
io.close
花辞树 2024-08-27 10:03:19

如果您多次需要它,您可以为 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, …

If you need it more than once, you could write an extension to 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, …
朱染 2024-08-27 10:03:19

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

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)

第一次玩时,它既不惯用,也不太直观,但很有趣!

Now that you've gotten reasonable answers, here's a completely different way to handle it.

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)

It's neither idiomatic, nor terribly intuitive the first time through, but it's fun!

画▽骨i 2024-08-27 10:03:19

在我的脑海中,但我确信通过更多的研究,有一种更优雅的方式

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| ... }

Off the top of my head but I'm sure with some more research there's a more elegant way

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

Okay scratch that... did a bit of research and this might be better

File.open( filename ).each_line.with_index.drop_while{ |line,index|  index == 0 }.each{ |line, index| ... }
我的痛♀有谁懂 2024-08-27 10:03:19

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

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

I doubt that this is idiomatic, but it's simple.

f = File.open(filename)
f.readline
f.each_line do |x|
   #...
end
烟柳画桥 2024-08-27 10:03:19

我认为您使用枚举器和 drop(1) 是正确的。由于某些奇怪的原因,虽然 Enumerable 定义了 #drop,但 Enumerator 没有。这是一个有效的 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

I think you are right on track with the Enumerator and drop(1). For some odd reason, while Enumerable defines #drop, Enumerator does not. Here is a working 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文