映射数组仅修改与特定条件匹配的元素 [英] Map an array modifying only elements matching a certain condition

查看:136
本文介绍了映射数组仅修改与特定条件匹配的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆