Question

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}
                      ];
Was it helpful?

Solution

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.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top