我有一个map,它要么改变一个值,要么将其设置为零.然后我想从列表中删除nil条目. list 不需要保留.

这就是我目前拥有的:

# A simple example function, which returns a value or nil
def transform(n)
  rand > 0.5 ? n * 10 : nil }
end

items.map! { |x| transform(x) } # [1, 2, 3, 4, 5] => [10, nil, 30, 40, nil]
items.reject! { |x| x.nil? } # [10, nil, 30, 40, nil] => [10, 30, 40]

我知道我可以做一个循环,然后有条件地收集到另一个数组中,如下所示:

new_items = []
items.each do |x|
    x = transform(x)
    new_items.append(x) unless x.nil?
end
items = new_items

但它似乎没有那么地道.有没有一种很好的方法可以将一个函数映射到一个列表上,同时删除/排除nils?

推荐答案

Ruby 2.7+

There is now!

Ruby 2.7为此推出了filter_map.这是一种惯用且有表现力的语言,我希望它很快就会成为常态.

例如:

numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]

在您的情况下,当块的计算结果为false时,只需:

items.filter_map { |x| process_x url }

"Ruby 2.7 adds Enumerable#filter_map"是一本关于这个主题的好书,其中列出了一些针对这个问题的早期方法的性能基准:

N = 100_000
enum = 1.upto(1_000)
Benchmark.bmbm do |x|
  x.report("select + map")  { N.times { enum.select { |i| i.even? }.map{ |i| i + 1 } } }
  x.report("map + compact") { N.times { enum.map { |i| i + 1 if i.even? }.compact } }
  x.report("filter_map")    { N.times { enum.filter_map { |i| i + 1 if i.even? } } }
end

# Rehearsal -------------------------------------------------
# select + map    8.569651   0.051319   8.620970 (  8.632449)
# map + compact   7.392666   0.133964   7.526630 (  7.538013)
# filter_map      6.923772   0.022314   6.946086 (  6.956135)
# --------------------------------------- total: 23.093686sec
# 
#                     user     system      total        real
# select + map    8.550637   0.033190   8.583827 (  8.597627)
# map + compact   7.263667   0.131180   7.394847 (  7.405570)
# filter_map      6.761388   0.018223   6.779611 (  6.790559)

Ruby相关问答推荐

如何在 Ruby 中创建可调用属性

如何判断一个对象在 Ruby 中是否可迭代?

如果 Java 人go Scala,C# go F#,那么 Ruby 人go 哪里寻求函数式?

当没有传入块时,是否有更好的方法来防止屈服?

在 RSpec-2.11 中使用隐含的 `subject` 和 `expect`

如何在 Ruby 中使用 (n) 诅咒?

Ruby:获取不带扩展名的文件名

如何将值保存到 YAML 文件中?

Ruby:module、require和include

如何在 Ruby 中找到除法的余数?

为什么显式返回会对 Proc 产生影响?

如何在 Ruby 中获取命名空间中的所有类名?

Mountain Lion rvm 安装 1.8.7 x11 错误

有条件的数组的第一个元素

运行 Ruby 命令时,PATH 中不安全的世界可写目录 /Users/username,模式 040777

Ruby 哈希白名单过滤器

Ruby 是否有像栈、队列、链表、映射或集合这样的容器?

将 Nokogiri 文档转换为 Ruby 哈希

如何在遍历数组时使用 Array#delete?

Ruby:如何将数组数组连接成一个