Ruby: until a new object has some property

How can I refactor the following code to avoid repetition?

  r = @lots.fetch @lots.keys.sample      
  until (neighbours r)
    r = @lots.fetch @lots.keys.sample

I basically have a new r object that is picked randomly and I need to pick r till the selected one doesn't respond to certain criteria (neighbours r). How can I refactor it to avoid the repetition of getting r and keep getting it till a condition is reached? Thanks


Personally I would shuffle @lots (turn it into a two element array if needed) and then use take_while like this:

>> h = {:a => 1, :b => 2, :c => 3} #=> {:a=>1, :b=>2, :c=>3}
>> h.to_a.shuffle.take_while { |k, v| v < 3 } #=> []
>> h.to_a.shuffle.take_while { |k, v| v < 3 } #=> [[:b, 2]]
>> h.to_a.shuffle.take_while { |k, v| v < 3 } #=> [[:a, 1]]
>> h.to_a.shuffle.take_while { |k, v| v < 3 } #=> [[:b, 2], [:a, 1]]

If you need the result as a hash again, just call Hash[] on it:

 >> Hash[h.to_a.shuffle.take_while { |k, v| v < 3 }] #=> {:a=>1}

In your case the condition for take while would be something like { |k, v| !(neighbours v)}. Also if you want the elements from the starting hash to be repeatable, you'll have to do use something else instead of shuffle.

  r = @lots.fetch @lots.keys.sample
end until neighbours r

Note that such code can easily lead to long running (or even infinite) loops if the condition neighbours is unlikely. In such cases better make sure you check every element just once as it is done in Michael Kohl's answer.

Need Your Help

jquery click event -

jquery click href

I want to perform an action when a user clicks on a div. However if he clicks on link within div, I want to send him directly to link. Now the href is being ignored.

django model field like view

django django-models

I'd like to have a model field that will return the latest related of another model.