all jazz
all jazz

Reputation: 2017

call function until (with call limit)

I have a function that generates random output (string).

I need to call that function until I get 3 different outputs (strings).

What is the most elegant way to generate array with 3 unique strings by calling the function, with the limit how many times the function can be called if the output is not generated in specified number of attempts?

Here's what I currently have:

output = []
limit_calls = 5
limit_calls.times do |i|
  str = generate_output_function
  output.push str
  break if output.uniq.size > 2
end

Can this be beautified / shortened to 1 line? I'm pretty sure in ruby.. :)

Thanks

Upvotes: 1

Views: 108

Answers (2)

froderik
froderik

Reputation: 4808

Using a set makes it (a bit) easier:

require 'set'
output = Set.new
limit_calls = 5
call_count = 0
while output.size < 3 and call_count < limit_calls
  output << generate_output_function 
  call_count += 1
end
output

or with an array

output = []
limit_calls = 5
while output.size < limit_calls and output.uniq.size < 3
  output << generate_output_function 
end
output.uniq

UPDATE with the call limit. Seems like the Array version wins! Thanks Iain!

Will also ponder a version using inject.

UPDATE 2 - with inject:

5.times.inject([]) { |a, el| a.uniq.size < 3 ? a << generate_output_function : a }

there is your oneliner. I am not sure I prefer it cause it is a bit hard to follow.....

Upvotes: 3

Jim Riordan
Jim Riordan

Reputation: 1428

Froderik's answer missed out the call_limit requirement. What about a function like...

def unique_string_array(call_limit)
  output = []
  calls = 0
  until (output.size == 3 || calls == call_limit) do
    (output << generate_output_function).uniq! && calls+=1
  end
  output
end

It isn't a one-liner but it is readable... with this implementation, you may end up with arrays less than size 3. The most important thing is that you have a test that asserts the behaviour you want! (in order to test this thoroughly you'll have to stub out the call to generate_output_function)

Upvotes: 1

Related Questions