映射一个数组,只修改匹配某个条件的元素 [英] Map an array modifying only elements matching a certain condition

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

问题描述

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

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