映射一个数组,只修改匹配某个条件的元素 [英] Map an array modifying only elements matching a certain condition
问题描述
在 Ruby 中,以这样一种方式映射数组的最具表现力的方式是:修改某些元素而其他元素保持不变?
In Ruby, what is the most expressive way to map an array in such a way that certain elements are modified and the others left untouched?
这是一种直接的方法:
old_a = ["a", "b", "c"] # ["a", "b", "c"]
new_a = old_a.map { |x| (x=="b" ? x+"!" : x) } # ["a", "b!", "c"]
如果不够,当然可以省略单独"的情况:
Omitting the "leave-alone" case of course if not enough:
new_a = old_a.map { |x| x+"!" if x=="b" } # [nil, "b!", nil]
我想要的是这样的:
new_a = old_a.map_modifying_only_elements_where (Proc.new {|x| x == "b"})
do |y|
y + "!"
end
# ["a", "b!", "c"]
在 Ruby 中是否有一些很好的方法可以做到这一点(或者 Rails 有一些我还没有找到的便捷方法)?
Is there some nice way to do this in Ruby (or maybe Rails has some kind of convenience method that I haven't found yet)?
感谢大家的回复.虽然你们集体说服我最好只使用带有三元运算符的 map
,但你们中的一些人发布了非常有趣的答案!
Thanks everybody for replying. While you collectively convinced me that it's best to just use map
with the ternary operator, some of you posted very interesting answers!
推荐答案
我同意 map 语句是好的.它清晰而简单,而且很容易任何人都可以维护.
I agree that the map statement is good as it is. It's clear and simple,, and would easy for anyone to maintain.
如果你想要更复杂的东西,这个怎么样?
If you want something more complex, how about this?
module Enumerable
def enum_filter(&filter)
FilteredEnumerator.new(self, &filter)
end
alias :on :enum_filter
class FilteredEnumerator
include Enumerable
def initialize(enum, &filter)
@enum, @filter = enum, filter
if enum.respond_to?(:map!)
def self.map!
@enum.map! { |elt| @filter[elt] ? yield(elt) : elt }
end
end
end
def each
@enum.each { |elt| yield(elt) if @filter[elt] }
end
def each_with_index
@enum.each_with_index { |elt,index| yield(elt, index) if @filter[elt] }
end
def map
@enum.map { |elt| @filter[elt] ? yield(elt) : elt }
end
alias :and :enum_filter
def or
FilteredEnumerator.new(@enum) { |elt| @filter[elt] || yield(elt) }
end
end
end
%w{ a b c }.on { |x| x == 'b' }.map { |x| x + "!" } #=> [ 'a', 'b!', 'c' ]
require 'set'
Set.new(%w{ He likes dogs}).on { |x| x.length % 2 == 0 }.map! { |x| x.reverse } #=> #<Set: {"likes", "eH", "sgod"}>
('a'..'z').on { |x| x[0] % 6 == 0 }.or { |x| 'aeiouy'[x] }.to_a.join #=> "aefiloruxy"
这篇关于映射一个数组,只修改匹配某个条件的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!