Xáo trộn một mảng với python, ngẫu nhiên hóa thứ tự mảng với python


261

Cách dễ nhất để xáo trộn một mảng với python là gì?


28
+1 để di chuyển các bit hữu ích nhất của tài liệu python sang định dạng SO Q & A luôn vượt trội.
charleslparker

1
Có một tùy chọn không làm thay đổi mảng ban đầu mà trả về một mảng được xáo trộn mới không?
Charlie Parker

5
bạn có thể nhận được một mảng mới (chưa sửa đổi) với new_array = random.sample( array, len(array) ).
Charlie Parker

Câu trả lời:


464
import random
random.shuffle(array)

3
Có một tùy chọn không làm thay đổi mảng ban đầu mà trả về một mảng được xáo trộn mới không?
Charlie Parker

@Charlie Đó sẽ là một điều tốt để hỏi trong một câu hỏi riêng biệt. (Có lẽ ai đó đã hỏi rồi.)
David Z

13
Trớ trêu thay, trang này lại là trang nổi tiếng nhất trên Google khi tôi vừa tìm kiếm "mảng xáo trộn trăn"
Joshua Huber

2
@Charlie mọi người Google những câu hỏi này để họ có thể tìm thấy câu trả lời cho họ trên những nơi như chồng tràn. Miễn là nó không phải là một bản sao, không có gì sai khi tạo ngăn xếp tràn một tùy chọn làm tài nguyên
Matt

@javadba Điều đó thực sự có nghĩa là một câu trả lời cho câu hỏi đầu tiên. Không có gì sai khi đặt câu hỏi về stack stack ngay cả khi nó có thể được tìm thấy với một số đào trên google. Nó cho phép những người trong tương lai tìm thấy câu trả lời trên stackoverflow khi họ tự đào.
Matt

108
import random
random.shuffle(array)

2
Có một tùy chọn không làm thay đổi mảng ban đầu mà trả về một mảng được xáo trộn mới không?
Charlie Parker

36

Cách khác để làm điều này bằng cách sử dụng 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)

Đầu ra:

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

Ưu điểm: Bạn có thể ngẫu nhiên nhiều mảng đồng thời mà không làm gián đoạn ánh xạ. Và 'Random_state' có thể kiểm soát sự xáo trộn cho hành vi có thể lặp lại.


1
Cảm ơn, rất hữu ích để xáo trộn hai mảng cùng một lúc.
Dmitry

1
Đã tìm kiếm điều này, TNX!
Nộp

2
câu này đầy đủ hơn (và thường hữu ích hơn) so với câu trả lời được chấp nhận
javadba

21

Các câu trả lời khác là dễ nhất, tuy nhiên hơi khó chịu khi random.shufflephương thức này không thực sự trả về bất cứ thứ gì - nó chỉ sắp xếp danh sách đã cho. Nếu bạn muốn xâu chuỗi các cuộc gọi hoặc chỉ có thể khai báo một mảng được xáo trộn trong một dòng bạn có thể làm:

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

Sau đó, bạn có thể làm các dòng như:

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

7
Nó không trả lại bất cứ điều gì cụ thể bởi vì nó đang cố gắng nhắc nhở bạn rằng nó hoạt động bằng cách thay đổi đầu vào tại chỗ. (Điều này có thể tiết kiệm bộ nhớ.) Chức năng của bạn cũng thay đổi đầu vào của nó.
John Y

2
Tôi đoán đó là một phong cách. Cá nhân tôi thích thực tế là tôi có thể viết một dòng duy nhất để đạt được những gì sẽ mất một vài cách khác. Đối với tôi, có vẻ lạ khi một ngôn ngữ nhằm cho phép các chương trình càng ngắn càng tốt không có xu hướng trả về đối tượng đã qua trong những trường hợp này. Vì nó thay đổi đầu vào tại chỗ, bạn có thể thay thế một cuộc gọi thành Random.shuffle cho một cuộc gọi đến phiên bản này mà không gặp vấn đề gì.
Mark Rhodes

12
Python không thực sự nhằm mục đích ngắn gọn nhất có thể. Python nhằm cân bằng khả năng đọc với biểu cảm. Nó xảy ra khá ngắn gọn, chủ yếu là vì nó là một ngôn ngữ cấp cao. Riêng built-in của Python thường (không phải luôn luôn) cố gắng hoặc là "functionlike" (trả về một giá trị, nhưng không có tác dụng phụ) hoặc là "procedurelike" (hoạt động thông qua các phản ứng phụ, và không quay trở lại bất cứ điều gì). Điều này đi đôi với sự phân biệt khá nghiêm ngặt giữa các câu lệnh và biểu thức của Python.
John Y

Đẹp. Tôi đề nghị đổi tên nó thành my_shuffle để thấy sự khác biệt trong mã ngay lập tức.
Jabba

Có thể, nhưng điều này có thể là tối ưu hóa sớm (nó có thể hữu ích, nhưng nhu cầu xáo trộn không đòi hỏi rõ ràng là cần phải trả về mảng). Ngoài ra, shuffle (mảng) theo sau là một số sử dụng shuffle sẽ chỉ là 2 dòng so với 3 + n (lần sử dụng), mặc dù tôi đoán nó sẽ tiết kiệm nếu bạn sử dụng nhiều lần. Đây là một video tuyệt vời thảo luận về loại điều này (ví dụ: yêu cầu ảo và tối ưu hóa sớm) - pyvideo.org/video/880/stop-wr- classes
Aaron Newton

12

Khi xử lý các danh sách Python thông thường, random.shuffle()sẽ thực hiện công việc giống như các câu trả lời trước đó hiển thị.

Nhưng khi đến ndarray( numpy.array), random.shuffledường như phá vỡ bản gốc ndarray. Đây là một ví dụ:

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

Chỉ dùng: np.random.shuffle(a)

Giống như random.shuffle, np.random.shufflexáo trộn các mảng tại chỗ.


2
phá hủy có nghĩa là gì, chính xác? (ý tôi là, trong bối cảnh này - tôi không phải là ELL.)
dbliss

Chà, nếu tôi thử A = np.array (phạm vi (9)). Định hình lại ([3,3])
Nicholas McCarthy

11

Chỉ trong trường hợp bạn muốn một mảng mới, bạn có thể sử dụng sample:

import random
new_array = random.sample( array, len(array) )

3

Bạn có thể sắp xếp mảng của bạn với khóa ngẫu nhiên

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

Phím chỉ được đọc một lần để so sánh mục trong khi sắp xếp vẫn hiệu quả.

nhưng có vẻ như random.shuffle(array)sẽ nhanh hơn vì nó được viết bằng C


1
điều này có tạo ra một phần tử ngẫu nhiên mới cho mỗi phần tử của mảng không?
javadba

@javadba Không, việc này chỉ sắp xếp một mảng theo chỉ số ngẫu nhiên sẽ kết thúc việc xáo trộn mảng
Trịnh Hoàng Nhu

1
Xin lỗi tôi có thể không rõ ràng Tôi không có nghĩa là arraytôi có nghĩa là Randomphần tử: tức là trong trường lambdahợp random.random()có thể tạo ra thể hiện Randomlớp mới mỗi lần. Tôi thực sự không chắc chắn: trong trường hợp javanày sẽ là cách làm sai: bạn nên tạo một Random rng = Random()và sau đó gọi rng.nextGaussian(). Nhưng không chắc chắn làm thế nào python random.random()hoạt động
javadba

1
Mặc dù mã của bạn có thể đúng như câu trả lời Nhưng Xây dựng mã của bạn làm gì, Nó có thể cải thiện chất lượng câu trả lời của bạn. Kiểm tra bài viết: Làm thế nào để tôi viết một câu trả lời tốt?
LuFFy

1

Ngoài các trả lời trước, tôi muốn giới thiệu một chức năng khác.

numpy.random.shufflecũng như random.shufflethực hiện xáo trộn tại chỗ. Tuy nhiên, nếu bạn muốn trả về một mảng bị xáo trộn numpy.random.permutationlà chức năng sử dụng.


1

Tôi không biết tôi đã sử dụng random.shuffle()nhưng nó trả lại 'Không' cho tôi, vì vậy tôi đã viết cái này, có thể hữu ích cho ai đó

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
vâng, nó trả về Không, nhưng mảng bị sửa đổi, nếu bạn thực sự muốn trả về một cái gì đó thì hãy nhập ngẫu nhiên def shuffle (Array):
Random.shuffle (Array

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

Xin lưu ý rằng random.shuffle()không nên sử dụng trên các mảng đa chiều vì nó gây ra sự lặp lại.

Hãy tưởng tượng bạn muốn xáo trộn một mảng dọc theo chiều thứ nhất của nó, chúng ta có thể tạo ví dụ thử nghiệm sau đây,

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

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

sao cho dọc theo trục thứ nhất, phần tử thứ i tương ứng với ma trận 2x3 trong đó tất cả các phần tử đều bằng i.

Nếu chúng ta sử dụng hàm xáo trộn chính xác cho các mảng đa chiều, nghĩa là np.random.shuffle(x), mảng sẽ được xáo trộn dọc theo trục đầu tiên như mong muốn. Tuy nhiên, sử dụng random.shuffle(x)sẽ gây ra sự lặp lại. Bạn có thể kiểm tra điều này bằng cách chạy len(np.unique(x))sau khi xáo trộn, cung cấp cho bạn 10 (như mong đợi) np.random.shuffle()nhưng chỉ khoảng 5 khi sử dụng random.shuffle().

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.