caa*_*os0 4 ruby erlang list-comprehension
我刚开始学习Erlang,并且非常喜欢他们的列表理解语法,例如:
Weather = [{toronto, rain}, {montreal, storms}, {london, fog}, {paris, sun}, {boston, fog}, {vancounver, snow}].
FoggyPlaces = [X || {X, fog} <- Weather].
Run Code Online (Sandbox Code Playgroud)
在这种情况下,FoggyPlaces将评估为"伦敦"和"波士顿".
在Ruby中执行此操作的最佳方法是什么?
例如,像一个数组(很常见,我相信):
weather = [{city: 'toronto', weather: :rain}, {city: 'montreal', weather: :storms}, {city: 'london', weather: :fog}, {city: 'paris', weather: :sun}, {city: 'boston', weather: :fog}, {city: 'vancounver', weather: :snow}]
Run Code Online (Sandbox Code Playgroud)
我现在最好的是:
weather.collect {|w| w[:city] if w[:weather] == :fog }.compact
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我必须调用compact删除nil值,并且示例本身不像Erlang那样可读.
而更在二郎示例中,city和weather是原子.我甚至不知道如何在Ruby中获得有意义且看起来很好的东西.
Jör*_*tag 10
首先,您的数据结构不相同.与Erlang示例等效的Ruby数据结构更像是
weather = [[:toronto, :rain], [:montreal, :storms], [:london, :fog],
[:paris, :sun], [:boston, :fog], [:vancouver, :snow]]
Run Code Online (Sandbox Code Playgroud)
其次,是的,Ruby没有列表推导或模式匹配.所以,例如将可能会更复杂.您的列表理解首先过滤所有模糊的城市,然后预测名称.让我们在Ruby中做同样的事情:
weather.select {|_, weather| weather == :fog }.map(&:first)
# => [:london, :boston]
Run Code Online (Sandbox Code Playgroud)
但是,Ruby以对象为中心,但您使用的是抽象数据类型.通过更加面向对象的数据抽象,代码可能看起来更像
weather.select(&:foggy?).map(&:city)
Run Code Online (Sandbox Code Playgroud)
这不是太糟糕,是吗?