1

配列に繰り返し要素がある可能性があることを考慮して、ある配列に別の配列のすべての要素が含まれているかどうかを(すばやく)判断したいと思います。

したがって、私は次のようなことを試みました:

alice = %w(a a a b)
bob = %w(a a b c d e)
alice & bob => ["a", "b"]
alice - bob => []

しかし、私が欲しいのは、bobには十分な「a」文字がないため、bobにaliceのすべての要素が含まれていないことを判別できる演算子です。

4

4 に答える 4

3

おそらく、各要素が発生する頻度を数えるのが最も簡単なので、数えた/数えなかった重複を追跡することについてあまり心配する必要はありません。

alice_counts = alice.each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }
#=> {"a"=>3, "b"=>1}

bob_counts = bob.each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }
#=> {"a"=>2, "b"=>1, "c"=>1, "d"=>1, "e"=>1}

次に、の各キーalice_countsの値が次の値以上であることを確認しbob_countsます。

alice_counts.all? { |k, v| bob_counts[k] >= v }
#=> false
于 2012-06-15T16:35:06.777 に答える
3
alice.select{|x| alice.count(x) > bob.count(x)}

更新 ベンチマークの設定:

require 'benchmark'

def subset_multivalue?(a, b)
  bb = b.clone
  a.each do |e|
    i = bb.index(e)
    if i
      bb.delete_at(i)
    else
      return false
    end
  end
  return true
end

def subset_multivalue2?(a, b)
  a.find{|x| a.count(x) > b.count(x)}
end

def subset_multivalue3?(alice, bob)
  alice_counts = alice.each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }
  bob_counts = bob.each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }

  alice_counts.all? do |k, v|
    bob_counts.has_key?(k) && bob_counts[k] >= v
  end
end

alice = %w(a a a b)
bob = %w(a a b c d e)

Benchmark.bm do |x|
  x.report("dave:") do
    1000000.times do
      subset_multivalue?(alice, bob)
    end
  end

  x.report("me:") do
    1000000.times do
      subset_multivalue2?(alice,bob)
    end
  end

  x.report("andrew:") do
    1000000.times do
      subset_multivalue3?(alice,bob)
    end
  end
end

結果:

       user     system      total        real
dave: 15.054000   0.000000  15.054000 ( 15.108864)
me: 11.529000   0.031000  11.560000 ( 11.689669)
andrew: 65.036000   0.047000  65.083000 ( 67.463859)
于 2012-06-16T01:42:50.280 に答える
0

私はこれに落ち着いていると思います:

def subset_multivalue?(a, b)
    bb = b.clone
    a.each do |e|
            i = bb.index(e)
            if i
                    bb.delete_at(i)
            else
                    return false
            end
    end
    return true
end

私はそれがそれほどルビーではないことを理解します、しかしそれは仕事をするようです。

于 2012-06-16T00:12:32.023 に答える
0

Enumerable#group_by()が選択されます。

alice = %w(a a a b)
bob = %w(a a b c d e)
alice_group = alice.group_by{|a| a}.map{|k,v| [k ,v.length]}
#=> [["a", 3], ["b", 1]]
bob_group = bob.group_by{|a| a}.map{|k,v| [k ,v.length]}
#=> [["a", 2], ["b", 1], ["c", 1], ["d", 1], ["e", 1]]
alice_group-bob_group
#=> [["a", 3]]
bob_group-alice_group
#=>[["a", 2], ["c", 1], ["d", 1], ["e", 1]]
于 2012-06-16T00:51:14.100 に答える