如何解决在 Ruby 中将迭代器转换为数组的单行程序
这必须是一个常见问题解答,但经过大量网络搜索后,我未能找到答案。我是 Ruby 编程语言的新手,所以我可能误解了一些基础知识,或者我将 C#、F# 或 Haskell 的知识投射到 Ruby 上。
如果我有一个像下面这样的方法,是否有一个单行将它变成数组或其他可变数据结构?
def foo
yield 8
yield 2
yield 5
end
我知道我可以做到:
ary = Array.new
foo { |x| ary << x }
然而,这不是单线。例如,在 C# 中,我可以使用 ToList
或 ToArray
扩展方法,或者在 F# 中,例如Seq.toList
:
let foo = seq {
yield 8
yield 2
yield 5
}
let arr = foo |> Seq.toList
Ruby 中是否有类似的单行代码?
还是我完全误解了 foo
的性质?
解决方法
实际上,您的问题中有两个独立的问题。
第一个问题在标题中:
Ruby 中将迭代器转换为数组的单行代码
这很简单:Enumerator
,在 Ruby 中被称为迭代器,混入(继承自)Enumerable
。 Enumerable
具有 Enumerable#to_a
方法,该方法从 Enumerable
创建 Array
,因此也从 Enumerator
创建,因为 Enumerator
IS -AN Enumerable
。
因此,如果您有 Enumerator
,您只需调用 to_a
,例如
some_enum.to_a
但是,您没有 Enumerator
。你有一个方法。因此,您没有问的真正问题是问题的关键:如何从方法创建 Enumerator
?
这就是 Object#enum_for
的作用:
enum = enum_for(:foo)
#=> #<Enumerator: ...>
ary = enum.to_a
#=> [8,2,5]
但是请注意,在许多情况下,您实际上并不需要 Array
,因为 Enumerator
就像 Enumerable
一样继承自 Array
,因此响应于许多相同的消息。
另请注意,按照惯例,Ruby 中有许多“迭代器”方法,例如Enumerable#map
、#each
等在没有块的情况下被调用时将返回 Enumerator
:
def foo
return enum_for(__callee__) { 3 } unless block_given?
yield 8
yield 2
yield 5
end
然后你可以简单地做:
enum = foo
#=> #<Enumerator: ...>
ary = enum.to_a
#=> [8,5]
,
一种惯用的方法是如果没有给出块就返回一个枚举器:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Button
y = np.random.randint(1,100,size=50)
y2 = np.random.randint(1,size=50)
fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()#Comment out the second axes,the annotation works.
dots1,= ax.plot(y,'r.',picker=True,label='data1')
dots2,= ax2.plot(y2,'g.',label='data2')
fig.legend()
anno = ax.annotate('N/A',xy=(0,0),xytext=(15,15),# update
textcoords=('offset pixels'),bbox=dict(boxstyle='round',fc='w',alpha=1),arrowprops=dict(arrowstyle='fancy')
)
anno.set_visible(False)
def motion(event):
x = event.xdata
y = event.ydata
v = anno.get_visible()
if event.inaxes in (ax,ax2): # update
c1,ind1 = dots1.contains(event)
c2,ind2 = dots2.contains(event)
if c1 or c2:
anno.xy = (x,y)
anno.set_text(f'{x}-{y}')
anno.set_visible(True)
if v:
anno.set_visible(False)
event.canvas.draw_idle()
fig.canvas.mpl_connect('motion_notify_event',motion)
plt.show()
这给你:
def foo
return enum_for(__method__) unless block_given?
yield 8
yield 2
yield 5
end
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。