【问题标题】:Do Ruby hashes have a method like `reject!` that returns matching items?Ruby 哈希是否有类似 `reject!` 的返回匹配项的方法?
【发布时间】:2012-04-17 19:58:01
【问题描述】:

Ruby 哈希是否有类似reject! 的方法,它返回匹配项并在哈希中只留下不匹配项?例如:

planets = {'Mars' => 2, 'Jupiter' => 63, 'Saturn' => 47}

few_moons = planets.some_method! do |planet, moon_count|
  moon_count < 50
end

few_moons #=> {'Mars'  => 2, 'Saturn' => 47}
planets   #=> {'Jupiter' => 63}

reject! 返回原始哈希,减去被拒绝的项目。 partition 很接近,但它返回元组数组,而不是哈希,并且不会修改原始哈希。

我在文档中没有看到类似的内容,我想在自己动手之前问问周围的情况。

【问题讨论】:

  • 我认为partition 是最接近的,并且没有太多工作可以打包以满足您的需求。

标签: ruby hash


【解决方案1】:
few_moons, many_moons = 
  planets.partition { |planet, moon_count| moon_count < 50 } \
  .map{ |v| Hash[v] }

【讨论】:

  • 不错:Hash['Jupiter', 63] #=&gt; {"Jupiter"=&gt;63}
  • 在这种情况下Hash[[['Jupiter', 63], ...]] #=&gt; {"Jupiter"=&gt;63, ...}
【解决方案2】:

一种解决方法是使用 Proc 两次:

moon_filter = Proc.new {|planet, moon_count| moon_count < 50 }
few_moons   = planets.select(&moon_filter)
lotsa_moons = planets.reject(&moon_filter)
planets     = lotsa_moons

【讨论】:

    【解决方案3】:

    还有Enumerable#group_by:

    planets_with = planets.group_by do |planet, moon_count|
      moon_count < 50 ? :many_moons : :few_moons
    end
    
    few  = planets_with[:few_moons]
    many = planets_with[:many_moons]
    

    但是,这将映射到数组数组而不是哈希数组。要解决这个问题:

    planets_with.merge!(planets_with) { |key, values| Hash[values] }
    

    【讨论】:

    • 我在哪里可以找回不匹配的行星? select! 丢弃它们。
    • @NathanLong,抱歉;我误解了你的问题。
    【解决方案4】:

    自己动手

    class Hash
      def reject_and_return!(&block)
        matches = {}
        self.each do |k, v|
          matches[k] = self.delete(k) if block.call(k, v)
        end
        matches
      end
    end
    

    按预期工作:

    planets = {'Mars' => 2, 'Jupiter' => 63, 'Saturn' => 47}
    
    few_moons = planets.reject_and_return! do |planet, moon_count|
      moon_count < 50
    end
    
    few_moons #=> {'Mars'  => 2, 'Saturn' => 47}
    planets   #=> {'Jupiter' => 63}
    

    【讨论】:

      【解决方案5】:

      Hash[] 构造函数将从分区中取回数组并按照您想要的方式将它们转换为哈希值。这不是一条线,但我认为它更干净:

      a, not_a = {a: 'b', c: 'd', e: 'f'}.partition{|k,v| k == :a} a=哈希[a] not_a = 哈希[not_a}

      【讨论】:

        猜你喜欢
        • 2011-12-05
        • 1970-01-01
        • 2017-11-07
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2021-05-11
        • 1970-01-01
        相关资源
        最近更新 更多