当前位置: 动力学知识库 > 问答 > 编程问答 >

ruby - On average, set true on every fifth item, but not in even order

问题描述:

I have a collection with 100 items.

In an iteration I want to set an object attribute to true on 20 % of the items.

But I don't want the setting of true to occur evenly, i.e. on every fifth item.

It's even OK if not exactly 20 % gets true, as long as the setting is not set evenly.

网友答案:

You can use rand:

def true_20_percent_of_the_time
  rand(5) == 0
end
网友答案:

An inefficient but concise way of accomplishing this would be to shuffle your array, slice the first 20 elements, then set the attributes on them.

items.shuffle[0..19].each do |item|
  item.foo = true
end

If you care about efficiency, you may want to look into modifying the Fisher Yates algorithm.

网友答案:

If you're generating the array:

ary = Array.new(2, true) + Array.new(8, false)
ary # => [true, true, false, false, false, false, false, false, false, false]
ary.shuffle # => [false, false, true, false, false, false, false, false, false, true]

That only uses 10 elements as an example, but I'm sure you can figure out how to adjust the count.

The above can be reduced to:

ary = (Array.new(2, true) + Array.new(8, false)).shuffle
# => [false, false, true, false, true, false, false, false, false, false]

And that can be reduced to:

ary = (([true] * 2) + ([false] * 8)).shuffle
# => [false, false, false, true, false, false, true, false, false, false]

If it's a pre-existing array:

ARRAY_SIZE = 10
ary = [false] * ARRAY_SIZE

Then you can slice it and reassign the number of true elements needed:

ary[0, (ARRAY_SIZE * 0.20).to_i] = [true] * (ARRAY_SIZE * 0.20)
ary # => [true, true, false, false, false, false, false, false, false, false]

And then shuffle it:

ary.shuffle # => [true, false, false, false, false, false, false, false, false, true]
网友答案:

Let's say you have the array

a = Array.new(21) { |i| i }
  #=> [0, 1, 2, 3,..., 19, 20]

and you wanted to choose exactly

(a.size/5.0).round #=> 4

elements randomly. Then you could write:

@lucky_ones = [*(0...a.size)].sample((a.size/5.0).round)
  #=> [6, 12, 3, 9]

a.each_with_index do |e,i|
  puts "Wow! I've been selected. I'm #{e}" if @lucky_ones.include? i
end

Wow! I've been selected. I'm 3
Wow! I've been selected. I'm 6
Wow! I've been selected. I'm 9
Wow! I've been selected. I'm 12
分享给朋友:
您可能感兴趣的文章:
随机阅读: