🗂

[Feature #16993] Hash#keys から Set を生成する Hash#keys_to_set メソッドを追加する提案

2025/02/19に公開

[Feature #16993] Sets: from hash keys using Hash#key_set

  • 現状 Hash のキーから Set のオブジェクトを生成する場合、以下のようにコードを書く必要がある
h = { a: 1, b: 2, c: 3 }
pp Set.new(h.keys)
# => #<Set: {:a, :b, :c}>
  • このときに Hash#keys を呼び出すコストがあるので、それを軽減するために以下のような Hash#key_set メソッドを追加する提案
    • 一時的に配列を作成したり、キーをすべて再ハッシュする必要がある、と書いてありますね
h = { a: 1, b: 2, c: 3 }
pp h.key_set
# => #<Set: {:a, :b, :c}>
  • 要は Set.new(h.keys) を行う専用のメソッドを追加したい、って話みたいですね
  • Set あんまり使わないんですがこういうコードって結構書いたりするんですかね?
  • パフォーマンスに関しては以下のようなベンチマークが提示されています
# frozen_string_literal: true
require 'set'
require 'benchmark/ips'

class Hash
  def key_set
    s = Set.new
    s.instance_variable_set(:@hash, transform_values { true })
    s
  end
end

size = 50
h = (1..size).to_h { |i| ['x' * i, nil] }

Benchmark.ips do |x|
  x.report("key_set")          { h.key_set }
  x.report("keys")             { Set.new(h.keys)  }
  x.report("new(each_key)")    { Set.new(h.each_key)  }
  x.report("each_key{}")       { h2 = {}; h.each_key {|k| h2[k] = true} ; h2  }
Calculating -------------------------------------
             key_set    244.549k (± 7.4%) i/s -      1.219M in   5.017876s
                keys     82.661k (± 2.3%) i/s -    417.400k in   5.052408s
       new(each_key)     75.002k (± 5.0%) i/s -    377.400k in   5.045102s
          each_key{}    114.757k (± 3.8%) i/s -    582.000k in   5.079700s
GitHubで編集を提案

Discussion