我目前正在使用Ruby版本1.8.7,我一直在寻找但无法找到解决方案。我目前正在创建一个独特的供应商标识符。但我会在这里简化问题。
我有供应商和产品的2D数组:
A = [["C"], ["A","D"], ["A","B"], ["B","C","E","F"], ["B","G","K"], [], ["H","I"], [], [], ["I"], ["J"]]
我需要做的是检索具有最多唯一产品数量的前5个用户(数组索引号)。在这种情况下。
前五大供应商将是:
1 - A,D
3 - B,C,E,F
4 - B,G,K
6 - H,I
10 - J
供应商3有产品["B","C","E","F"]
但供应商4有产品[“B”,“G”,“K”]。
由于供应商4和3都有["B"]
供应商3有 3个独特产品 ["C","E","F"]
供应商4有 2个独特产品 ["G","K"]
我需要返回的是前五大供应商的供应商数组(基于二维数组中的索引)。
到目前为止,这是我的代码:
def test
vendors = [[C], [A,D], [A,B], [B,C,E,F], [B,G,K], [], [H,I], [], [], [I], [J]]
useridArr = Array(0..vendors.length-1)
vendors = inplace_quicksort(vendors, 0, vendors.length-1,useridArr)
getUnique(vendors,useridArr, vendors.length-1)
end
def partition_array(array, left, right, pivot_index, arr)
pivot_value = array[pivot_index].length
arr[pivot_index], arr[right] = arr[right], arr[pivot_index]
array[pivot_index], array[right] = array[right], array[pivot_index]
store_index = left
(left..right-1).each do |i|
if array[i].length < pivot_value
arr[i], arr[store_index] = arr[store_index], arr[i]
array[i], array[store_index] = array[store_index], array[i]
store_index = store_index + 1
end
end
arr[store_index], arr[right] = arr[right], arr[store_index]
array[store_index], array[right] = array[right], array[store_index]
return store_index
end
def inplace_quicksort(array, left, right, indexArr)
if left < right
pivot_index = (left + ((right - left) / 2)).to_i
new_pivot_index = partition_array(array, left, right, pivot_index,indexArr)
inplace_quicksort(array, left, new_pivot_index - 1,indexArr)
inplace_quicksort(array, new_pivot_index + 1, right,indexArr)
end
return array
end
def getUnique(vendors,useridArr, searchFor)
while searchFor != -1
p vendors.map {|a| a & vendors[searchFor] }
searchFor = searchFor - 1
end
end
答案 0 :(得分:2)
11
的每个A
元素都对应一个供应商,并且(巧合)11
个产品 1 :
A = [[:C], [:A, :D], [:A, :B], [:B, :C, :E, :F], [:B, :G, :K], [],
[:H, :I], [], [], [:I], [:J]]
products = A.flatten
#=> [:C, :A, :D, :A, :B, :B, :C, :E, :F, :B, :G, :K, :H, :I, :I, :J]
products.uniq
#=> [:C, :A, :D, :B, :E, :F, :G, :K, :H, :I, :J]
products.uniq.size
#=> 11
我们首先计算每种产品的实例数量:
g = Hash.new(0)
counts = products.each_with_object(g) { |p,h| h[p] += 1 }
#=> {:C=>2, :A=>2, :D=>1, :B=>3, :E=>1, :F=>1, :G=>1, :K=>1,
# :H=>1, :I=>2, :J=>1}
g = Hash.new(0)
创建一个空哈希值,默认值为零。这意味着,如果g
没有密钥k
,则g[k]
将返回零。注意表达式h[p] += 1
。这称为缩写分配。它只是意味着表达式扩展为:
h[p] = h[p] + 1
在评估之前。如果h
没有密钥p
,则右侧的h[p]
会返回零,因此h[p]
设置为0+1 #=> 1
。
以上所有内容通常会更紧凑地写成如下:
counts = A.flatten.each_with_object(Hash.new(0)) { |p,h| h[p] += 1 }
仅由一家供应商提供的产品由以下人员提供:
unique_products = counts.select { |_,count| count == 1 }.keys
#=> [:D, :E, :F, :G, :K, :H, :J]
3
偏移A
的供应商有两个独特的产品:E
和:F
:
[:B,:C,:E,:F] & unique_products
#=> [:E, :F]
那是:
([:B,:C,:E,:F] & unique_products).size
#=> 2
如果我们想要五个独特产品数量最多的供应商,按照减少数量的独特产品排序,我们可以这样做:
A.sort_by { |a| -(a & unique_products).size }.first(5)
#=> [[:B, :G, :K], [:B, :C, :E, :F], [:H, :I], [:A, :D], [:J]]
在Ruby 2.2+中,我们可以使用Enumerable#max_by更直接地执行此操作:
A.max_by(5) { |a| (a & unique_products).size }
#=> [[:B, :G, :K], [:B, :C, :E, :F], [:J], [:A, :D], [:H, :I]]
订购略有不同,但这是因为前五名的最后三家供应商都有一种独特的产品。
总结一下,我们可以写一个方法如下:
def max_unique_products(products_by_vendor, n)
counts = products_by_vendor.flatten.
each_with_object(Hash.new(0)) { |p,h| h[p] += 1 }
unique_products = counts.select { |_,count| count == 1 }.keys
products_by_vendor.max_by(n) { |a| (a & unique_products).size }
end
max_unique_products(A, 5)
#=> [[:B, :G, :K], [:B, :C, :E, :F], [:J], [:A, :D], [:H, :I]]
编辑1:我忘了您想要顶级供应商的索引。只需将上述方法的最后一行更改为:
products_by_vendor.each_with_index.
max_by(n) { |a,_| (a & unique_products).size }.map(&:last)
或:
products_by_vendor.each_with_index.
sort_by { |a,_| -(a & unique_products).size }.first(5).map(&:last)
你会得到:
max_unique_products(A, 5)
#=> [4, 3, 10, 1, 6]
编辑2:要使用Ruby v1.8.7,请尝试以下方法:
def max_unique_products(products_by_vendor, n)
counts = products_by_vendor.flatten.
reduce(Hash.new(0)) { |h,p| h[p] += 1; h }
unique_products = counts.select { |_,count| count == 1 }.map(&:first)
products_by_vendor.each_with_index.
sort_by { |a,_| -(a & unique_products).size }.first(5).map(&:last)
end
它适用于v2.2,我相信所有方法都存在于v1.8.7中。
1。 OP最初将A定义为[[C],[A,D] ...]。我在答案中将其改为[[:C],[:A,:D] ...]。 lostcoder然后将其改为[[“C”],[“A”,“D”] ......]。