Как считать дубликаты хэшей в Ruby 1.8.5 ( Sketchup Ruby API)
Мне нужно посчитать дубликаты, они должны быть на 100% идентичны, чтобы увеличить мой счет, но я не могу использовать ничего из Ruby 1.8.5, этот код будет запускаться внутри плагина в 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}
];
2 ответа
Короткий ответ:
h = Hash.new 0
product_list.each {|p| h[p] += 1}
product_list_result = h.keys.map{|k| k["count"] = h[k]; k}
Более длинный ответ, объясняющий, как это работает. Начиная с ваших данных:
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}
Теперь у вас есть хэш с продуктами в качестве ключей и считается как значения:
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}
Теперь преобразуйте его в желаемый формат массива:
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
Что приводит к:
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}
]
Преобразование массива можно сделать более кратко:
product_list_result = h.keys.map{|k| k["count"] = h[k]; k}
h.keys возвращает массив ключей из хэша h, который является просто уникальными продуктами в вашем списке. Затем карта функций заменяет каждый объект в этом массиве результатом следующего блока, который просто добавляет значение счетчика в хэш продукта.
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
для того, чтобы не изменять оригинал product_list
Проверено в ruby 1.8.7