我有一个问题数组,想从中随机获取一个不重复的问题。例如,有5个问题,如果全部问完,我将重新开始。我希望将其放入一个方法(或类似方法)中。
def askrandom
questions = ["A?", "B?" , "C?" , "D?"]
return #random question
end
输出应该类似于:
A? C? D? B? #所有问题都被问了一次,因此要重复
B? D? C? A? ...
我有一个问题数组,想从中随机获取一个不重复的问题。例如,有5个问题,如果全部问完,我将重新开始。我希望将其放入一个方法(或类似方法)中。
def askrandom
questions = ["A?", "B?" , "C?" , "D?"]
return #random question
end
A? C? D? B? #所有问题都被问了一次,因此要重复
B? D? C? A? ...
def initialize
@remaining_questions = []
end
让我们将问题提取到一个自己的方法中:
def questions
["A?", "B?" , "C?" , "D?"]
end
@remaining_questions
为空,则使用questions
的随机副本对其进行初始化。然后,您只需删除(并返回)第一个项目即可。def ask_random
@remaining_questions = questions.shuffle if @remaining_questions.empty?
@remaining_questions.shift
end
@remaining_questions ||= questions.shuffle
会不会显得过于设计了? - Aleksei Matiushkin[]
是真值。 - Stefanask_random
应该返回一个问题,而且你可以无限调用它。因此会有额外的开销。 - Stefan@remaining_questions = []
这一部分。 - Stefan这个解决方案与@Stefan的解决方案非常接近,只是想法稍微改变了一下。
class Questions
def initialize(array_of_questions)
@questions = array_of_questions
@nums ||= get_nums
end
def get_nums
(0...@questions.size).to_a.shuffle
end
def get_num
@nums.pop or (@nums = get_nums).pop
end
def pick
@questions[get_num]
end
end
questions = Questions.new(["A", "B", "C", "D"])
10.times.map{ questions.pick }
#=> ["B", "D", "C", "A", "C", "A", "B", "D", "A", "B"]
纯函数式方法:
def ask(question)
question.tap { |q| puts "Asking question #{q}" }
end
def askrandom(asked = [], remaining = ["A?", "B?" , "C?" , "D?"].shuffle)
return asked if remaining.empty?
askrandom(asked << ask(remaining.pop), remaining)
end
question.tap { |q| puts "Asking question #{q}" }
而不是简单的 puts "Asking question #{question}"
。你为什么在这里使用了 tap
? - fl00rnil
。 - ndnenkovdef fire_away(questions)
@n = (@n || -1) + 1
@order = [*0...questions.size].shuffle if @n % questions.size == 0
questions[@order.shift]
end
q = ["A?", "B?" , "C?" , "D?"]
fire_away q #=> "D?"
fire_away q #=> "A?"
fire_away q #=> "C?"
fire_away q #=> "B?"
fire_away q #=> "B?"
fire_away q #=> "C?"
fire_away q #=> "A?"
fire_away q #=> "D?"
fire_away q #=> "A?"
fire_away q #=> "C?"
fire_away q #=> "B?"
fire_away q #=> "D?"
你可能还需要这个方法
def reset_questions
@n = nil
end
fire_away
的类中可见的实例变量(并避免需要reset_questions
方法):def fire_away(questions)
n = -1
order = nil
Proc.new do
n += 1
order = [*0...questions.size].shuffle if n % questions.size == 0
questions[order.shift]
end
end
iterator = fire_away ["A", "B", "C", "D"]
iterator.call #=> "C"
iterator.call #=> "A"
iterator.call #=> "B"
iterator.call #=> "D"
iterator.call #=> "D"
class Questions
def initialize(*questions)
@questions = questions
@n = -1
end
def next_question
@n += 1
@order = [*0...@questions.size].shuffle if @n % @questions.size == 0
@questions[@order.shift]
end
end
q = Questions.new("A?", "B?" , "C?" , "D?")
q.next_question #=> "C?"
q.next_question #=> "A?"
q.next_question #=> "D?"
q.next_question #=> "B?"
q.next_question #=> "B?"
这两个修改显然比我的原始答案更优秀。
fire_away(q1); fire_away(q2)
。 - fl00r通常我会创建一个新数组,然后在随机后将值附加到新数组中,前提是该值在新数组中不存在。
如果你得到与上次相同的输出,那么这意味着输出已经在新数组中,因为你已经将它附加到了新数组中。
对于我的拙劣英语表示抱歉。