在 Ruby 和 Python 中使用 Yield 创建列表

发布于 2024-07-14 07:28:24 字数 571 浏览 10 评论 0原文

我正在尝试想出一种优雅的方法来从在 Python 和 Ruby 中生成值的函数创建列表。

在 Python 中:

def foo(x):
    for i in range(x):
        if bar(i): yield i 
result = list(foo(100))

在 Ruby 中:

def foo(x)
  x.times {|i| yield i if bar(i)}
end
result = []
foo(100) {|x| result << x}

虽然我喜欢使用两种语言工作,但我总是对 Ruby 版本必须初始化列表然后填充它感到有点困扰。 Python 的 yield 可以实现简单的迭代,这非常棒。 Ruby 的 yield 调用一个块,这也很棒,但是当我只想填充一个列表时,感觉有点笨拙。

有没有更优雅的 Ruby 方式?

更新 重新设计了示例以表明函数生成的值的数量不一定等于 x。

I'm trying to come up with an elegant way of creating a list from a function that yields values in both Python and Ruby.

In Python:

def foo(x):
    for i in range(x):
        if bar(i): yield i 
result = list(foo(100))

In Ruby:

def foo(x)
  x.times {|i| yield i if bar(i)}
end
result = []
foo(100) {|x| result << x}

Although I love working in both languages, I've always been a bit bothered by the Ruby version having to initialize the list and then fill it. Python's yield results in simple iteration, which is great. Ruby's yield invokes a block, which is also great, but when I just want to fill a list, it feels kinda clunky.

Is there a more elegant Ruby way?

UPDATE Reworked the example to show that the number of values yielded from the function isn't necessarily equal to x.

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

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

发布评论

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

评论(7

不离久伴 2024-07-21 07:28:24

因此,对于您的新示例,请尝试以下操作:

def foo(x)
  (0..x).select { |i| bar(i) }
end

基本上,除非您正在编写自己的迭代器,否则您在 Ruby 中并不经常需要 yield 。 如果您停止尝试使用 Ruby 语法编写 Python 习惯用法,您可能会做得更好。

So, for your new example, try this:

def foo(x)
  (0..x).select { |i| bar(i) }
end

Basically, unless you're writing an iterator of your own, you don't need yield very often in Ruby. You'll probably do a lot better if you stop trying to write Python idioms using Ruby syntax.

奈何桥上唱咆哮 2024-07-21 07:28:24

对于 Python 版本,我将使用生成器表达式,例如:

(i for i in range(x) if bar(i))

或者对于过滤值的这种特定情况,甚至更简单

itertools.ifilter(bar,range(x))

For the Python version I would use a generator expression like:

(i for i in range(x) if bar(i))

Or for this specific case of filtering values, even more simply

itertools.ifilter(bar,range(x))
┼── 2024-07-21 07:28:24

与 Python 代码(使用 Ruby 生成器)完全相同的代码是:

def foo(x)
    Enumerator.new do |yielder|
        (0..x).each { |v| yielder.yield(v) if bar(v) }
    end
end

result = Array(foo(100))

在上面,列表是延迟生成的(就像在 Python 示例中一样); 看:

def bar(v); v % 2 == 0; end

f = foo(100)
f.next #=> 0
f.next #=> 2

The exact equivalent of your Python code (using Ruby Generators) would be:

def foo(x)
    Enumerator.new do |yielder|
        (0..x).each { |v| yielder.yield(v) if bar(v) }
    end
end

result = Array(foo(100))

In the above, the list is lazily generated (just as in the Python example); see:

def bar(v); v % 2 == 0; end

f = foo(100)
f.next #=> 0
f.next #=> 2
活雷疯 2024-07-21 07:28:24

我知道这并不完全是您想要的,但是用 ruby​​ 表达示例的更优雅的方式是:

result = Array.new(100) {|x| x*x}

I know it's not exactly what you were looking for, but a more elegant way to express your example in ruby is:

result = Array.new(100) {|x| x*x}
梦里梦着梦中梦 2024-07-21 07:28:24

对于 stbuton 发布的 Python 列表理解版本,如果您需要使用 xrange 而不是 range想要一台发电机。 range 将在内存中创建整个列表。

For the Python list comprehension version posted by stbuton use xrange instead of range if you want a generator. range will create the entire list in memory.

知你几分 2024-07-21 07:28:24

yield 在 ruby​​ 和 python 中意味着不同的东西。 在 ruby​​ 中,如果我没记错的话,你必须指定一个回调块,而 python 中的生成器可以传递并屈服于持有它们的人。

yield means different things ruby and python. In ruby, you have to specify a callback block if I remember correctly, whereas generators in python can be passed around and yield to whoever holds them.

我爱人 2024-07-21 07:28:24
def squares(x)
  (0..x).map { |i| i * i }
end

任何涉及一系列值的事情最好用一个范围来处理,而不是times和数组生成。

def squares(x)
  (0..x).map { |i| i * i }
end

Anything involving a range of values is best handled with, well, a range, rather than times and array generation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文