สับเปลี่ยนอาร์เรย์ด้วย python สุ่มลำดับของรายการอาร์เรย์ด้วย python


261

วิธีที่ง่ายที่สุดในการสลับอาเรย์ด้วยไพ ธ อนคืออะไร?


28
+1 สำหรับการย้ายบิตที่มีประโยชน์มากที่สุดของเอกสารหลามไปยังฟอร์แมต SO Q&A ที่เหนือกว่าเสมอ
charleslparker

1
มีตัวเลือกที่ไม่กลายพันธุ์อาร์เรย์เดิม แต่ส่งกลับอาร์เรย์แบบสับใหม่หรือไม่
Charlie Parker

5
คุณจะได้รับอาเรย์ใหม่ (ยังไม่แปร) new_array = random.sample( array, len(array) )ด้วย
Charlie Parker

คำตอบ:


464
import random
random.shuffle(array)

3
มีตัวเลือกที่ไม่กลายพันธุ์อาร์เรย์เดิม แต่ส่งกลับอาร์เรย์แบบสับใหม่หรือไม่
Charlie Parker

@ Charlie ที่จะเป็นสิ่งที่ดีที่จะถามในคำถามแยกต่างหาก (อาจมีคนอื่นถามไปแล้ว)
David Z

13
กระแทกแดกดันหน้านี้ได้รับความนิยมสูงสุดใน Google เมื่อฉันค้นหา "python shuffle array"
Joshua Huber

2
@ คนชาร์ลี Google คำถามเหล่านี้เพื่อให้พวกเขาสามารถหาคำตอบพวกเขาในสถานที่ต่าง ๆ เช่นกองล้น ตราบใดที่มันไม่ซ้ำกันก็ไม่มีอะไรผิดปกติกับการทำ stack overflow เป็นตัวเลือกให้เป็นทรัพยากร
Matt

@javadba นั่นจริงๆแล้วหมายถึงการตอบคำถามแรก ไม่มีอะไรผิดปกติในการถามคำถามเกี่ยวกับการล้นสแต็กแม้ว่าจะพบได้ในการขุดบน google ช่วยให้ผู้คนในอนาคตสามารถค้นหาคำตอบของ stackoverflow เมื่อพวกเขาขุดเอง
แมตต์


36

ทางเลือกอื่นในการทำสิ่งนี้โดยใช้sklearn

from sklearn.utils import shuffle
X=[1,2,3]
y = ['one', 'two', 'three']
X, y = shuffle(X, y, random_state=0)
print(X)
print(y)

เอาท์พุท:

[2, 1, 3]
['two', 'one', 'three']

ข้อได้เปรียบ: คุณสามารถสุ่มหลายอาร์เรย์พร้อมกันโดยไม่กระทบการแมป และ 'random_state' สามารถควบคุมการสับสำหรับพฤติกรรมที่ทำซ้ำได้


1
ขอขอบคุณมันมีประโยชน์มากในการสลับสองอาร์เรย์พร้อมกัน
Dmitry

1
มองหาสิ่งนี้ TNX!
nOp

2
นี้เป็นที่สมบูรณ์มากขึ้น (และมักจะมีประโยชน์มากขึ้นกว่า) ได้รับการยอมรับคำตอบ
javadba

21

คำตอบอื่น ๆ นั้นง่ายที่สุด แต่ก็น่ารำคาญนิดหน่อยที่random.shuffleวิธีนี้ไม่ได้ส่งคืนอะไรเลย - เพียงเรียงลำดับรายการที่กำหนด หากคุณต้องการเชื่อมโยงสายหรือเพียงแค่สามารถประกาศอาร์เรย์แบบสับในหนึ่งบรรทัดคุณสามารถทำได้:

    import random
    def my_shuffle(array):
        random.shuffle(array)
        return array

จากนั้นคุณสามารถทำบรรทัดเช่น:

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):

7
ไม่ส่งคืนสิ่งใดเป็นพิเศษเพราะพยายามเตือนให้คุณทำงานได้โดยเปลี่ยนอินพุตให้เข้าที่ (สิ่งนี้สามารถบันทึกหน่วยความจำได้) ฟังก์ชั่นของคุณจะเปลี่ยนแปลงอินพุตของมันเอง
John Y

2
ฉันคิดว่ามันเป็นสไตล์ โดยส่วนตัวแล้วฉันชอบความจริงที่ว่าฉันสามารถเขียนบรรทัดเดียวเพื่อให้บรรลุสิ่งที่จะใช้เวลาสองสามอย่างอื่น มันแปลกสำหรับฉันว่าภาษาที่มีจุดประสงค์เพื่อให้โปรแกรมสั้นที่สุดเท่าที่จะทำได้ไม่น่าจะคืนค่าวัตถุที่ส่งผ่านในกรณีเหล่านี้ เนื่องจากเป็นการเปลี่ยนแปลงอินพุตที่คุณสามารถแทนที่การโทรเป็น random.shuffle สำหรับการโทรไปที่เวอร์ชันนี้โดยไม่มีปัญหา
Mark Rhodes

12
Python ไม่ได้ตั้งใจให้สั้นที่สุดเท่าที่จะเป็นไปได้ Python มีจุดมุ่งหมายเพื่อสร้างความสมดุลในการอ่านด้วยการแสดงออก มันจึงค่อนข้างสั้นโดยเฉพาะอย่างยิ่งเพราะเป็นภาษาระดับสูงมาก งูหลามของตัวเองสร้างขึ้นอินโดยทั่วไป (ไม่เสมอไป) มุ่งมั่นที่จะทั้งเป็น "functionlike" (คืนค่า แต่ไม่ได้มีผลข้างเคียง) หรือจะเป็น "procedurelike" (ใช้งานผ่านทางผลข้างเคียงและไม่กลับอะไร) สิ่งนี้ไปควบคู่กับความแตกต่างที่เข้มงวดระหว่าง Python กับข้อความและสำนวน
John Y

ดี ฉันแนะนำให้เปลี่ยนชื่อเป็น my_shuffle เพื่อดูความแตกต่างในรหัสทันที
Jabba

อาจ แต่นี่อาจเป็นการเพิ่มประสิทธิภาพก่อนวัยอันควร (อาจเป็นประโยชน์ แต่ความต้องการในการสลับไม่จำเป็นต้องส่งคืนอาร์เรย์อย่างชัดเจน) นอกจากนี้สับเปลี่ยน (อาเรย์) ตามด้วยการใช้งานแบบสุ่มบางอย่างจะเป็นเพียง 2 บรรทัดซึ่งตรงข้ามกับ 3 + n (การใช้งานครั้ง) ถึงแม้ว่าฉันเดาว่ามันจะเป็นการประหยัดถ้าคุณใช้มันหลายครั้ง นี่คือวิดีโอที่ยอดเยี่ยมที่กล่าวถึงประเภทของสิ่งนี้ (เช่นข้อกำหนดเรื่องแฟนทอมและการปรับให้เหมาะสมก่อนวัย) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton

12

เมื่อจัดการกับรายการ Python ปกติงานrandom.shuffle()จะทำตามคำตอบก่อนหน้านี้ที่แสดง

แต่เมื่อมันมาถึงndarray( numpy.array) ดูเหมือนว่าจะทำลายเดิมrandom.shuffle ndarrayนี่คือตัวอย่าง:

import random
import numpy as np
import numpy.random

a = np.array([1,2,3,4,5,6])
a.shape = (3,2)
print a
random.shuffle(a) # a will definitely be destroyed
print a

เพียงใช้: np.random.shuffle(a)

ชอบrandom.shuffle, np.random.shuffleshuffles อาร์เรย์ในสถานที่


2
สิ่งที่ทำลายหมายถึงอะไรกันแน่? (ฉันหมายถึงในบริบทนี้ - ฉันไม่ใช่ ELL)
dbliss

ถ้าฉันลอง A = np.array (ช่วง (9)). ก่อร่างใหม่ ([3,3])
Nicholas McCarthy


3

คุณสามารถจัดเรียงอาร์เรย์ของคุณด้วยปุ่มสุ่ม

sorted(array, key = lambda x: random.random())

อ่านคีย์เพียงครั้งเดียวเพื่อเปรียบเทียบรายการระหว่างการเรียงลำดับที่มีประสิทธิภาพ

แต่ดูเหมือนว่าrandom.shuffle(array)จะเร็วขึ้นเนื่องจากเขียนเป็นภาษาซี


1
สิ่งนี้สร้างองค์ประกอบแบบสุ่มใหม่สำหรับแต่ละองค์ประกอบของอาร์เรย์หรือไม่
javadba

@javadba ไม่นี่แค่เรียงลำดับอาเรย์โดยสุ่มดัชนีซึ่งจะทำให้สับเปลี่ยนอาเรย์
Trinh Hoang Nhu

1
ขออภัยผมอาจจะไม่ล้างผมไม่ได้หมายความว่าarrayฉันหมายถึง Randomองค์ประกอบ: คือในอาจจะมีการสร้างใหม่เช่นชั้นในแต่ละครั้ง ฉันไม่แน่ใจว่าจริง: ในนี้จะเป็นวิธีที่ไม่ถูกต้องที่จะทำมัน: คุณควรสร้างแล้วเรียก แต่ไม่แน่ใจว่าไพ ธ อนทำงานอย่างไรlambdarandom.random()RandomjavaRandom rng = Random()rng.nextGaussian()random.random()
javadba

1
ในขณะที่รหัสของคุณอาจแก้ไขเป็นคำตอบ แต่อธิบายว่ารหัสของคุณทำอะไร แต่สามารถปรับปรุงคุณภาพของคำตอบของคุณได้ ชำระเงินบทความ: ฉันจะเขียนคำตอบที่ดีได้อย่างไร
LuFFy

1

นอกจากคำตอบก่อนหน้านี้ฉันอยากจะแนะนำฟังก์ชั่นอื่น

numpy.random.shuffleเช่นเดียวกับrandom.shuffleการสับในสถานที่ อย่างไรก็ตามหากคุณต้องการส่งกลับอาเรย์แบบสับnumpy.random.permutationเป็นฟังก์ชันที่ใช้


1

ฉันไม่รู้ว่าฉันใช้random.shuffle()แต่กลับมาที่ 'ไม่มี' สำหรับฉันดังนั้นฉันจึงเขียนสิ่งนี้อาจเป็นประโยชน์กับใครบางคน

def shuffle(arr):
    for n in range(len(arr) - 1):
        rnd = random.randint(0, (len(arr) - 1))
        val1 = arr[rnd]
        val2 = arr[rnd - 1]

        arr[rnd - 1] = val1
        arr[rnd] = val2

    return arr

2
ใช่มันจะคืนค่า None แต่อาเรย์จะถูกปรับเปลี่ยนถ้าคุณต้องการส่งคืนบางสิ่งให้ลองทำการนำเข้า def def แบบสุ่ม (arr): random.shuffle (arr) return arr
user781903

0
# arr = numpy array to shuffle

def shuffle(arr):
    a = numpy.arange(len(arr))
    b = numpy.empty(1)
    for i in range(len(arr)):
        sel = numpy.random.random_integers(0, high=len(a)-1, size=1)
        b = numpy.append(b, a[sel])
        a = numpy.delete(a, sel)
    b = b[1:].astype(int)
    return arr[b]

0

ระวังว่าrandom.shuffle()ไม่ควรใช้กับอาเรย์หลายมิติเนื่องจากเป็นสาเหตุให้เกิดซ้ำ

ลองนึกภาพคุณต้องการสับเปลี่ยนอาร์เรย์ตามมิติแรกของมันเราสามารถสร้างตัวอย่างทดสอบต่อไปนี้

import numpy as np
x = np.zeros((10, 2, 3))

for i in range(10):
   x[i, ...] = i*np.ones((2,3))

ดังนั้นตามแกนแรกองค์ประกอบ i-th จะสอดคล้องกับเมทริกซ์ 2x3 โดยที่องค์ประกอบทั้งหมดมีค่าเท่ากับ i

หากเราใช้ฟังก์ชันสับเปลี่ยนที่ถูกต้องสำหรับอาร์เรย์หลายมิตินั่นคือnp.random.shuffle(x)อาร์เรย์จะถูกสับตามแกนแรกตามที่ต้องการ อย่างไรก็ตามการใช้random.shuffle(x)จะทำให้เกิดการซ้ำซ้อน คุณสามารถตรวจสอบโดยการทำงานlen(np.unique(x))หลังจากสับที่ช่วยให้คุณ 10 (ตามคาด) มีnp.random.shuffle()แต่เพียงประมาณ 5 random.shuffle()เมื่อใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.