我有一个包含一些字符串值的Ruby数组.我需要:
现在我的解决方案看起来像这样:
def example
matchingLines = @lines.select{ |line| ... }
results = matchingLines.map{ |line| ... }
return results.uniq.sort
end
Run Code Online (Sandbox Code Playgroud)
是否有一个Array或Enumerable方法将select和map组合成一个逻辑语句?
Jed*_*der 103
我通常使用map和compact我的选择标准一起作为后缀if.compact摆脱了nils.
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}
=> [3, 3, 3, nil, nil, nil]
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}.compact
=> [3, 3, 3]
Run Code Online (Sandbox Code Playgroud)
Ada*_*erg 50
你可以使用reduce它,只需要一次传递:
[1,1,1,2,3,4].reduce([]) { |a, n| a.push(n*3) if n==1; a }
=> [3, 3, 3]
Run Code Online (Sandbox Code Playgroud)
换句话说,将状态初始化为您想要的(在我们的例子中,填充空列表:) [],然后始终确保返回此值并修改原始列表中的每个元素(在我们的示例中,修改后的元素)推到列表中).
这是最有效的,因为它只通过一次传递(map+ select或compact需要两次传递)在列表上循环.
在你的情况下:
def example
results = @lines.reduce([]) do |lines, line|
lines.push( ...(line) ) if ...
lines
end
return results.uniq.sort
end
Run Code Online (Sandbox Code Playgroud)
hen*_*tha 17
接近这个的另一种不同方式是使用新的(相对于这个问题)Enumerator::Lazy:
def example
@lines.lazy
.select { |line| line.property == requirement }
.map { |line| transforming_method(line) }
.uniq
.sort
end
Run Code Online (Sandbox Code Playgroud)
该.lazy方法返回一个惰性枚举器.调用.select或.map在惰性枚举器上返回另一个惰性枚举器.只有在调用.uniq它之后才会强制执行枚举器并返回一个数组.所以真正发生的事是你.select和.map呼叫合并成一个-你只遍历@lines一次做两.select和.map.
我的直觉是亚当的reduce方法会快一点,但我认为这更具可读性.
这样做的主要结果是没有为每个后续方法调用创建中间数组对象.在正常@lines.select.map情况下,select返回一个数组,然后map再次返回一个数组.相比之下,延迟评估仅创建一次数组.当您的初始集合对象很大时,这很有用.它还使您能够使用无限的枚举器 - 例如random_number_generator.lazy.select(&:odd?).take(10).
hir*_*lau 10
如果你有一个select可以使用caseoperator(===),grep是一个很好的选择:
p [1,2,'not_a_number',3].grep(Integer){|x| -x } #=> [-1, -2, -3]
p ['1','2','not_a_number','3'].grep(/\D/, &:upcase) #=> ["NOT_A_NUMBER"]
Run Code Online (Sandbox Code Playgroud)
如果我们需要更复杂的逻辑,我们可以创建lambda:
my_favourite_numbers = [1,4,6]
is_a_favourite_number = -> x { my_favourite_numbers.include? x }
make_awesome = -> x { "***#{x}***" }
my_data = [1,2,3,4]
p my_data.grep(is_a_favourite_number, &make_awesome) #=> ["***1***", "***4***"]
Run Code Online (Sandbox Code Playgroud)
SRa*_*ack 10
Ruby 2.7以上
现在有!
Ruby 2.7正是filter_map为此目的而引入的。它是惯用语言和高性能,我希望它很快会成为标准。
例如:
numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]
Run Code Online (Sandbox Code Playgroud)
希望对某人有用!
我不确定有没有.该可枚举模块,增加了select和map,不显示的.
你需要传递两个块到该select_and_transform方法,这将是一个有点不直观的恕我直言.
显然,您可以将它们链接在一起,这更具可读性:
transformed_list = lines.select{|line| ...}.map{|line| ... }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
48053 次 |
| 最近记录: |