【问题标题】:Ruby: replacing elements in array based on their valueRuby:根据值替换数组中的元素
【发布时间】:2015-11-19 19:18:15
【问题描述】:

我检查了this questionthat other similar question,它们都没有提供用多个测试值替换数组元素的解决方案。

我有一个 Ruby 数组:

array = ["america", "europe", "asia", "africa", "france", "usa", "spain", "paris", "los angeles"]

我想转换这个数组,得到以下结果:

array = ["continent", "continent", "continent", "continent", "country", "country", "country", "city", "city"]

我的第一次尝试是这样做:

array.collect! do |element|
  (element == "america") ? "continent" : element
  (element == "europe") ? "continent" : element
  (element == "asia") ? "continent" : element
  (element == "africa") ? "continent" : element
  (element == "france") ? "country" : element
  (element == "usa") ? "country" : element
  (element == "spain") ? "country" : element
  (element == "paris") ? "city" : element
  (element == "los angeles") ? "city" : element
end

这段代码有两个问题:

  1. 我不确定这是使用 Ruby blockdo end 的方法。

  2. 此代码不是DRY,我相信我可以使用一组三个case 循环,一个用于大陆,一个用于国家,一个用于城市。

【问题讨论】:

    标签: arrays ruby


    【解决方案1】:

    这是一个更好的方法

    array.collect! do |element|
      case element
      when 'america', 'europe', 'asia', 'africa'
        'continent'
      when 'france', 'spain'
        'country'
      when 'paris', 'los angeles'
        'city'
      else
        element
      end
    end
    

    【讨论】:

    • 一个小注释——collectmap的别名。
    【解决方案2】:

    我会使用哈希来进行查找。这是 O(1) 并且非常简单。如果键不存在,则 fetch 的第二个参数是默认值。

    INDEX = {
      "america" => "continent", 
      "europe" => "continent", 
      "asia" => "continent", 
      "africa" => "continent", 
      "france" => "country", 
      "usa" => "country", 
      "spain" => "country", 
      "paris" => "city", 
      "los angeles" => "city"
    }
    
    [
      "america", 
      "europe", 
      "asia", 
      "africa", 
      "france", 
      "usa", 
      "spain", 
      "paris", 
      "los angeles", 
      "not indexed"
    ].map{|key| INDEX.fetch(key, key) }
    

    【讨论】:

      【解决方案3】:

      你不能得到比这更多的 DRY。 (还要注意这与 TJ Singleton 所做的非常相似)

      array = ["america", "europe", "asia", "africa", "france", "usa", "spain", "paris", "los angeles"]
      
      definitions = {
        "continent" => ["america", "europe", "asia", "africa"],
        "country" => ["france", "usa", "spain"],
        "city" => ["paris", "los angeles"],
        "planet" => ["mars","earth"]
      }
      
      inverse_array = definitions.map {|k,v| v.map { |e| [e, k]}}.flatten(1)
      inverse_hash = Hash[inverse_array]
      
      output = array.map { |e| inverse_hash[e] }
      puts output.inspect
      

      【讨论】:

      • 我喜欢你的方法,但建议definitions.flat_map { |k,v| v.product [k] }.to_h.values_at *array
      • 啊哈,代码人真好!我现在只是在想“嗯,肯定有比这个flatten(1) 更优雅的东西......”大了!
      • 与原始代码的一个区别是它不会处理值,但您使用 Hash.new 来提供默认值。 inverse_hash = Hash.new {|散列,键|钥匙 }; inverse_array = 定义.each {|k,v| v.每个 {|e| inverse_hash[e] = k }}
      【解决方案4】:

      使用Set 来跟踪一个大陆、国家和城市是什么来清理它怎么样?一组中的查找是 O(1),所以你在这里穿起来也不会更糟:

      continents = Set.new ["america", "europe", "asia", "africa"]
      countries = Set.new ["france", "usa", "spain"]
      cities = Set.new ["paris", "los angeles"]
      
      array = ["america", "europe", "asia", "africa", "france", "usa", "spain", "paris", "los angeles"]
      
      newArray = array.map{ |c|
      puts c
        if continents.include? c
          'continent' 
        elsif countries.include? c
          'country' 
        elsif cities.include? c
          'city'
        else
          'unknown'
        end
      }
      

      另一种使用地图的解决方案,我们创建一个查找表,其中键是大洲/国家/城市,值是相应的字符串“大陆”、“国家”或“城市”:

      continents = ["america", "europe", "asia", "africa"].each_with_object({}) { |k,h| h[k] = 'continent' }
      countries = ["france", "usa", "spain"].each_with_object({}) { |k,h| h[k] = 'country' }
      cities = ["paris", "los angeles"].each_with_object({}) { |k,h| h[k] = 'city' }
      
      array = ["america", "europe", "asia", "africa", "france", "usa", "spain", "paris", "los angeles"]
      
      newArray = array.map{ |c| continents[c] || countries[c] || cities[c] || c }
      

      【讨论】:

      • 带有多行块的花括号? :)
      猜你喜欢
      • 1970-01-01
      • 2019-10-14
      • 2014-05-07
      • 1970-01-01
      • 2022-06-21
      • 1970-01-01
      • 1970-01-01
      • 2020-03-19
      • 2016-07-13
      相关资源
      最近更新 更多