问题
I need to count the duplicates, they need to be 100% identical to increase my count, but I can not use a nothing out of Ruby 1.8.5, this code will run inside a plugin in google sketchup
Google Sketchup Ruby API
puts VERSION
1.8.5
puts RUBY_PLATFORM
i686-darwin8.10.1
product = 'Glass'
x = width
y = length
z = density
product_list = [
{ "product" => 1, "x" => 200, "y" => 100, "z" => 18},
{ "product" => 1, "x" => 200, "y" => 100, "z" => 18},
{ "product" => 1, "x" => 300, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 300, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 100, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 100, "y" => 100, "z" => 18},
{ "product" => 3, "x" => 100, "y" => 100, "z" => 18}
];
product_list_result = product_list.count_duplicate();
product_list_result = [
{ "product" => 1, "x" => 200, "y" => 100, "z" => 18, "count" = 2},
{ "product" => 1, "x" => 300, "y" => 100, "z" => 18, "count" = 1},
{ "product" => 2, "x" => 300, "y" => 100, "z" => 18, "count" = 1},
{ "product" => 2, "x" => 100, "y" => 100, "z" => 18, "count" = 2},
{ "product" => 3, "x" => 100, "y" => 100, "z" => 18, "count" = 1}
];
回答1:
Short answer:
h = Hash.new 0
product_list.each {|p| h[p] += 1}
product_list_result = h.keys.map{|k| k["count"] = h[k]; k}
Longer answer explaining how this works. Starting with your data:
product_list = [
{ "product" => 1, "x" => 200, "y" => 100, "z" => 18},
{ "product" => 1, "x" => 200, "y" => 100, "z" => 18},
{ "product" => 1, "x" => 300, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 300, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 100, "y" => 100, "z" => 18},
{ "product" => 2, "x" => 100, "y" => 100, "z" => 18},
{ "product" => 3, "x" => 100, "y" => 100, "z" => 18}
];
# First, create a hash to count the number of unique products. Have the initial
# count be 0.
h = Hash.new 0
# Add each product to the hash count.
product_list.each {|p| h[p] += 1}
Now you have a hash with products as keys, and counts as values:
h = {{"z"=>18, "y"=>100, "x"=>100, "product"=>3}=>1, {"z"=>18, "y"=>100, "x"=>300, "product"=>1}=>1, {"z"=>18, "y"=>100, "x"=>200, "product"=>1}=>2, {"z"=>18, "y"=>100, "x"=>300, "product"=>2}=>1, {"z"=>18, "y"=>100, "x"=>100, "product"=>2}=>2}
Now convert it to the array format you desire:
product_list_result = []
h.keys.each do |k|
# since each key is a product hash, we can add count to it
k["count"] = h[k]
# Now, add that to the array
product_list_result << k
end
Which results in:
product_list_result = [
{"z"=>18, "y"=>100, "x"=>100, "product"=>3, "count"=>1},
{"z"=>18, "y"=>100, "x"=>300, "product"=>1, "count"=>1},
{"z"=>18, "y"=>100, "x"=>200, "product"=>1, "count"=>2},
{"z"=>18, "y"=>100, "x"=>300, "product"=>2, "count"=>1},
{"z"=>18, "y"=>100, "x"=>100, "product"=>2, "count"=>2}
]
The array conversion can be done more succinctly:
product_list_result = h.keys.map{|k| k["count"] = h[k]; k}
h.keys returns an array of keys from hash h, which is just the unique products in your list. The function map then replaces each object in that array with the result of the block that follows which simply adds the count value to the product hash.
回答2:
product_list.dup.group_by { |h| h }.each_value.map do |value|
value.first.tap { |hash| hash['count'] = value.count }
end
=> [{"product"=>1, "x"=>200, "y"=>100, "z"=>18, "count"=>2},
{"product"=>1, "x"=>300, "y"=>100, "z"=>18, "count"=>1},
{"product"=>2, "x"=>300, "y"=>100, "z"=>18, "count"=>1},
{"product"=>2, "x"=>100, "y"=>100, "z"=>18, "count"=>2},
{"product"=>3, "x"=>100, "y"=>100, "z"=>18, "count"=>1}]
dup
is for to not modify original product_list
Tested in ruby 1.8.7
来源:https://stackoverflow.com/questions/12236656/how-to-count-duplicates-hash-itens-in-ruby-1-8-5-sketchup-ruby-api