Ruby 如何选择每个块中的项目?

Ruby 如何选择每个块中的项目?,ruby,arrays,Ruby,Arrays,如何选择每个块中的项目?或者,从相反的角度考虑,如何修改select块中的项目 例如,给定一个整数数组,如何拒绝奇数,返回一个偶数数组,同时向其中添加10?在下面的示例中,我希望返回[12,14,16] 尝试使用选择: a = (1..6).to_a a.select! do |i| if i % 2 == 0 a[a.find_index(i)] += 10 # This doesn't stick. true # this works end end p a # =&

如何选择
每个
块中的项目?或者,从相反的角度考虑,如何修改
select
块中的项目

例如,给定一个整数数组,如何拒绝奇数,返回一个偶数数组,同时向其中添加10?在下面的示例中,我希望返回
[12,14,16]

尝试使用
选择

a = (1..6).to_a
a.select! do |i|
  if i % 2 == 0
    a[a.find_index(i)] += 10 # This doesn't stick.
    true # this works
  end
end
p a # => [2, 4, 6]
尝试使用每个

a = (1..6).to_a
a.each do |i|
  if i % 2 == 0
    a[a.find_index(i)] += 10
  else
    a.delete(a.find_index(i)) # I suppose this isn't working?
  end
end
p a # => [1, 12, 3, 14, 5, 16]

使用
map
要转换数组的成员,只需从块中返回所需的新值,而不是在数组中设置新值。对于要拒绝的值,返回
nil

a = (1..6).to_a
a.map! do|i|
  if i % 2 == 0
    i + 10
  end
end.compact!
p a # => [12, 14, 16] 
更新: 由于多次通过的问题经常出现,这里有一个带有平面图的单次通过解决方案:

a = (1..6).to_a
a = a.flat_map do|i|
  if i.even? #happy?
    [i + 10]
  else
    []
  end
end
p a # => [12, 14, 16] 

遗憾的是,没有
平面地图所以我们必须重新分配
一个

使用
地图
要转换数组的成员,只需从块中返回所需的新值,而不是在数组中设置新值。对于要拒绝的值,返回
nil

a = (1..6).to_a
a.map! do|i|
  if i % 2 == 0
    i + 10
  end
end.compact!
p a # => [12, 14, 16] 
更新: 由于多次通过的问题经常出现,这里有一个带有平面图的单次通过解决方案:

a = (1..6).to_a
a = a.flat_map do|i|
  if i.even? #happy?
    [i + 10]
  else
    []
  end
end
p a # => [12, 14, 16] 

遗憾的是,没有
平面地图因此我们必须重新分配
a

您可以使用select删除所有奇数,并使用map执行您想要的附加操作:

a.select { |x| x % 2 == 0 }.map { |x| x + 10 }
=> [12, 14, 16]

可以使用“选择”删除所有奇数,并使用“映射”执行所需的其他操作:

a.select { |x| x % 2 == 0 }.map { |x| x + 10 }
=> [12, 14, 16]

出于好奇,您还可以在Ruby>=2中使用Ruby的惰性枚举

mega_range = (1..100_000)

filtered_collection = mega_range.lazy.select do |n|
    puts "selecting #{n}"
    n.even?
end.map do |n|
    puts "mapping #{n}"
    n * 2
end

filtered_collection.take(10).to_a

# selecting 1
# selecting 2
# mapping 2
# selecting 3
# selecting 4
# mapping 4
# selecting 5
# selecting 6
# mapping 6
# selecting 7
# selecting 8
# mapping 8
#  => [4, 8, 12, 16]
如您所见,将合并
select
map
操作,其中
map
仅对所选事件执行


不需要对集合进行额外的传递(这就是
compact!
所做的)。

出于好奇,您还可以在Ruby>=2中使用Ruby的惰性枚举

mega_range = (1..100_000)

filtered_collection = mega_range.lazy.select do |n|
    puts "selecting #{n}"
    n.even?
end.map do |n|
    puts "mapping #{n}"
    n * 2
end

filtered_collection.take(10).to_a

# selecting 1
# selecting 2
# mapping 2
# selecting 3
# selecting 4
# mapping 4
# selecting 5
# selecting 6
# mapping 6
# selecting 7
# selecting 8
# mapping 8
#  => [4, 8, 12, 16]
如您所见,将合并
select
map
操作,其中
map
仅对所选事件执行

无需对集合进行额外的传递(这就是
compact!
所做的)。

只需尝试以下方法:

>> (1..6).select(&:even?).map { |x| x + 10 }
=> [12, 14, 16]
简单地尝试一下:

>> (1..6).select(&:even?).map { |x| x + 10 }
=> [12, 14, 16]

我认为仅仅使用select是不可能实现您的目标的,它不能修改任何元素

以下是其他备选方案(可能与上面的一些答案重复):


我认为仅仅使用select是不可能实现您的目标的,它不能修改任何元素

以下是其他备选方案(可能与上面的一些答案重复):



Ruby有内置的方法
。甚至?
<代码>选择{x | x%2==0}
->
选择(&:偶数?
回答不错(+1),但我会接受另一个。就我的目的而言,问题的一部分是在单个块中包含变量,因此对我来说效果更好一些。@。我对通用解决方案更感兴趣。Ruby有内置的方法
。甚至?
<代码>选择{x | x%2==0}
->
选择(&:偶数?
回答不错(+1),但我会接受另一个。就我的目的而言,问题的一部分是在单个块中包含变量,因此对我来说效果更好一些。@。我对一般解决方案更感兴趣。太好了!非常优雅(在我的例子中,数组是零自由启动的,所以这很好)。因为我们在这个解决方案中对数组进行了两次遍历,我认为
miluz
的另一个解决方案对于相同的性能特征更具可读性。相反,使用
I%2==0
可以将其替换为
I。甚至?
@Jesper我可能会给出一个更好的示例,但这更适合我,因为我可以使用限制在此块中的每个项目的变量。根据我下面的说明,
inject
map]慢35%!。紧凑型。我还对平面地图进行了基准测试,速度慢了70%。我有点惊讶,但双通道解决方案似乎是最有效的。完美!非常优雅(在我的例子中,数组是零自由启动的,所以这很好)。因为我们在这个解决方案中对数组进行了两次遍历,我认为
miluz
的另一个解决方案对于相同的性能特征更具可读性。相反,使用
I%2==0
可以将其替换为
I。甚至?
@Jesper我可能会给出一个更好的示例,但这更适合我,因为我可以使用限制在此块中的每个项目的变量。根据我下面的说明,
inject
map]慢35%!。紧凑型。我还对平面地图进行了基准测试,速度慢了70%。我有点惊讶,但是双通道解决方案似乎是最有效的;我没有得到任何输出。如果我删除
.lazy
(并缩小范围),它将按预期工作(同时显然会处理整个范围)。包含
.lazy
后,最终输出不是数组,而是
啊,好的,它不会按原样计算第一部分,但是如果您通过(例如)将
过滤的集合
从可枚举集合转换为
,将
添加到
最后一行。是的,我会将该调用添加到
。到
谢谢。也感谢你让我对
懒惰
(+1)感兴趣,尽管我做了一些基准测试,发现它比没有基准测试慢得多。这看起来很有趣,但似乎不起作用;我没有得到任何输出。如果我删除
.lazy
(并缩小范围),它将按预期工作(同时显然会处理整个范围)。包含
.lazy
后,最终输出不是数组,而是
#
啊好的,它不会按原样计算第一部分,但是如果从枚举中转换
筛选的集合
,它会计算