如果我有数组:
ar = [1,3,5,3,6,1,4,6,7,6,6,6,6,6]
我可以将其减少到出现的次数:
counts = {1=>2, 3=>2, 5=>1, 6=>7, 4=>1, 7=>1}
现在,我想随机选择 ,其中ar
中使用最少的数字是 more 权重
我了解如何轻松地根据最常用的数字(而不是其倒数)做出加权随机选择。
答案 0 :(得分:3)
看来这对您有用:
arr = [1,3,5,3,6,1,4,6,7,6,6,6,6,6]
arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v|
[k] * v
end.sample
我们对元素进行分组并对其进行计数,然后创建一个新的Array
,其中元素的数量反转以支持较少的出现。例如
arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v|
[k] * v
end.group_by(&:itself).transform_values(&:size)
#=> {1=>7, 3=>7, 5=>14, 6=>2, 4=>14, 7=>14}
由于5最初发生一次,所以现在发生14次(与4和7相同)。 因此,5,4和7的选择可能性相同,分别是1和3的两倍,而1和3的出现是6的两倍和7倍。
也许这样的事情可能更有效
grouping =arr.group_by(&:itself).transform_values(&:size).
scale = grouping.values.uniq.reduce(&:lcm)
grouping.flat_map do |k, v|
[k] * (scale / v)
end.sample
答案 1 :(得分:1)
如果您已经有了一种用于进行随机加权选择的算法,则交换权重的一种方法如下。
grouping = ar.group_by { |n| n }.transform_values(&:size)
#=> {1=>2, 3=>2, 5=>1, 6=>7, 4=>1, 7=>1}
weights = grouping.values.uniq.sort
#=> [1, 2, 7]
reverse_mapping = weights.zip(weights.reverse).to_h
#=> {1=>7, 2=>2, 7=>1}
grouping.transform_values{ |v| reverse_mapping[v] }
#=> {1=>2, 3=>2, 5=>7, 6=>1, 4=>7, 7=>7}
就是这个想法。
res = ar.group_by { |n| n }.transform_values(&:size).then do |h|
rev_map = h.values.uniq.sort.then { |w| w.zip(w.reverse).to_h }
h.transform_values{ |v| rev_map[v] }
end
#=> {1=>2, 3=>2, 5=>7, 6=>1, 4=>7, 7=>7}