映射数组仅修改与特定条件匹配的元素 [英] 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?
这是一种直截了当的方式:
This is a straight-forward way to do it:
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]
我是什么希望是这样的:
What I would like is something like this:
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屋!