ฉันจะเลือกแบบสุ่มจากอาร์เรย์ได้อย่างไร


559

ฉันต้องการทราบว่ามีวิธีที่สะอาดกว่านี้มากในการทำสิ่งนี้หรือไม่ โดยทั่วไปฉันต้องการเลือกองค์ประกอบแบบสุ่มจากอาเรย์ที่มีความยาวผันแปรได้ โดยปกติฉันจะทำเช่นนี้:

myArray = ["stuff", "widget", "ruby", "goodies", "java", "emerald", "etc" ]
item = myArray[rand(myarray.length)]

มีบางอย่างที่อ่าน / ง่ายกว่าในการแทนที่บรรทัดที่สองหรือไม่? หรือว่าเป็นวิธีที่ดีที่สุดที่จะทำ ฉันคิดว่าคุณสามารถทำได้myArray.shuffle.firstแต่ฉันเห็นเพียง#shuffleไม่กี่นาทีที่ผ่านมาดังนั้นฉันยังไม่ได้ใช้จริงๆ


13
คำตอบที่ดีด้านล่าง แต่เป็นจุดทั่วไปเกี่ยวกับการสลับเพลง ฉันคิดว่าการทนต่ออาเรย์เต็มรูปแบบนั้นจะเข้มข้นกว่าการรับจำนวนสุ่มดังนั้นมันจะไม่เป็นไปในทิศทางที่ดี
Derek Organ

คำตอบ:


1127

เพียงใช้Array#sample:

[:foo, :bar].sample # => :foo, or :bar :-)

มันมีอยู่ใน Ruby 1.9.1+ เพื่อให้สามารถใช้กับทับทิมเวอร์ชันก่อนหน้า require "backports/1.9.1/array/sample"ได้

โปรดทราบว่าใน Ruby 1.8.7 มันมีอยู่ภายใต้ชื่อที่โชคร้ายchoice; มันถูกเปลี่ยนชื่อเป็นเวอร์ชั่นใหม่กว่าดังนั้นคุณไม่ควรใช้มัน

แม้ว่าจะไม่มีประโยชน์ในกรณีนี้ให้sampleยอมรับอาร์กิวเมนต์ตัวเลขในกรณีที่คุณต้องการตัวอย่างจำนวนมาก


1
ฉันควรจะรู้ว่าคุณจะมีคำตอบที่สมบูรณ์แบบสำหรับฉัน (เนื่องจากคำถาม Ruby ส่วนใหญ่ที่ฉันเรียกดูที่นี่มีการป้อนข้อมูลของคุณบางแห่ง) ฉันดีใจที่คุณชี้ให้เห็นเวอร์ชัน ฉันใช้ 1.9.2 apidock (ความคิดเห็นของ mladen) ไม่มีตัวอย่าง ทั้งทับทิม - doc ในความเห็นของคุณการอ้างอิงที่ดีที่สุดสำหรับ Ruby อัพเดตเป็น 1.9 คืออะไร
พอลฮอฟเฟอร์

ในหมายเหตุด้านข้างเหมาะสมหรือไม่ที่จะเปลี่ยน "คำตอบที่ถูกต้อง" หลังจากที่ฉันเลือกคำตอบอื่นเป็นครั้งแรก
พอลฮอฟเฟอร์

1
ขอบคุณ :-) และใช่มันเป็นกำลังใจ (ดูmeta.stackexchange.com/questions/19448/ … )
Marc-André Lafortune

ฉันสังเกตเห็นการแก้ไขของคุณลบการกล่าวถึง 1.8.8 มันยังคงมีอยู่ในหัว 1.8 และคุณเพียงแค่แก้ไขคำถามเพราะ 1.8.8 จะไม่เกิดขึ้น?
Andrew Grimm

3
@Andrew: ใช่ฉันแก้ไขคำตอบของฉันเพราะ 1.8.8 จะไม่เกิดขึ้น มันควรจะยังคงอยู่ในหัว 1.8 แต่สาขานั้นตาย :-(
Marc-André Lafortune

84

myArray.sample(x) ยังสามารถช่วยให้คุณรับองค์ประกอบสุ่ม x จากอาเรย์


6
มันน่าสังเกตว่า my_array.sample (1)! = my_array.sample
Redithion

5
@Redithion มันก็น่าสังเกตว่าความแตกต่างระหว่าง: my_array.sample (1) == [ตัวอย่าง] และ my_array.sample == ตัวอย่างเพื่อให้ชัดเจนว่าคุณหมายถึงอะไร
Ekkstein


12

จำนวนสุ่มของไอเท็มสุ่มจากอาเรย์

def random_items(array)
  array.sample(1 + rand(array.count))
end

ตัวอย่างของผลลัพธ์ที่เป็นไปได้:

my_array = ["one", "two", "three"]
my_array.sample(1 + rand(my_array.count))

=> ["two", "three"]
=> ["one", "three", "two"]
=> ["two"]

@fwilson ชุดสุ่มของวัตถุในลำดับใด ๆ ยังดีสำหรับการทดสอบชุดค่าผสมที่แตกต่างกันหรือสร้างข้อมูลต้นขั้ว
Mike Rapadas

ทำไมไม่ขยายคลาส Array? [] .total_random จะดูเท่ห์กว่า มาทับทิมของมัน มันมีวัตถุประสงค์!
Tim Kretschmer

สิ่งนี้จะไม่ส่งคืนอาร์เรย์ว่าง คุณต้องวาง1 +ในที่อื่น
sawa

0
arr = [1,9,5,2,4,9,5,8,7,9,0,8,2,7,5,8,0,2,9]
arr[rand(arr.count)]

นี่จะส่งคืนองค์ประกอบแบบสุ่มจากอาร์เรย์

หากคุณจะใช้บรรทัดที่กล่าวถึงด้านล่าง

arr[1+rand(arr.count)]

จากนั้นในบางกรณีมันจะส่งคืนค่า 0 หรือค่าศูนย์

บรรทัดที่กล่าวถึงด้านล่าง

rand(number)

ส่งคืนค่าเสมอจาก 0 ถึง number-1

ถ้าเราใช้

1+rand(number)

จากนั้นมันอาจส่งคืนหมายเลขและ arr [number] ไม่มีองค์ประกอบ


-2
class String

  def black
    return "\e[30m#{self}\e[0m"
  end

  def red
    return "\e[31m#{self}\e[0m"
  end

  def light_green
    return "\e[32m#{self}\e[0m"
  end

  def purple
    return "\e[35m#{self}\e[0m"
  end

  def blue_dark
    return "\e[34m#{self}\e[0m"
  end

  def blue_light
    return "\e[36m#{self}\e[0m"
  end

  def white
    return "\e[37m#{self}\e[0m"
  end


  def randColor
    array_color = [
      "\e[30m#{self}\e[0m",
      "\e[31m#{self}\e[0m",
      "\e[32m#{self}\e[0m",
      "\e[35m#{self}\e[0m",
      "\e[34m#{self}\e[0m",
      "\e[36m#{self}\e[0m",
      "\e[37m#{self}\e[0m" ]

      return array_color[rand(0..array_color.size)]
  end


end
puts "black".black
puts "red".red
puts "light_green".light_green
puts "purple".purple
puts "dark blue".blue_dark
puts "light blue".blue_light
puts "white".white
puts "random color".randColor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.