वस्तुओं की एक सूची में फेरबदल


770

मेरे पास वस्तुओं की एक सूची है और मैं उन्हें फेरबदल करना चाहता हूं। मुझे लगा कि मैं random.shuffleविधि का उपयोग कर सकता हूं , लेकिन यह तब विफल हो जाता है जब सूची वस्तुओं की होती है। वहाँ वस्तुओं फेरबदल या इस के आसपास एक और तरीका है?

import random

class A:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1, a2]

print(random.shuffle(b))

यह असफल हो जाएगा।


6
क्या आप एक उदाहरण दे सकते हैं कि यह कैसे विफल हो जाता है? random.shuffle सूची में वस्तुओं के प्रकार के लिए अपरिवर्तनशील कार्य करना चाहिए।
बायर जू

3
>>> a1 = (a) >>> a2 = (a) >>> b = [a1, a2] >>> b [<__ main __। 0xb7df9e6c पर एक उदाहरण, <__ मुख्य ____ 0xb7df9e2c>> पर एक उदाहरण। >> प्रिंट random.shuffle (b) कोई नहीं
utdiscant

135
जैसा कि नीचे कहा गया है, random.shuffle एक नई फेरबदल सूची वापस नहीं करता है; यह सूची में जगह फेरबदल करता है। इसलिए आपको "random.shuffle (b)" प्रिंट नहीं करना चाहिए और इसके बजाय एक लाइन पर फेरबदल करना चाहिए और अगली लाइन पर b प्रिंट करना चाहिए।
एली कोर्टराइट

यदि आप सुन्न सरणियों को फेरबदल करने की कोशिश कर रहे हैं, तो नीचे मेरा जवाब देखें।
गॉर्डन बीन

1
क्या कोई विकल्प है जो मूल सरणी को म्यूट नहीं करता है लेकिन एक नया शिल्ड सरणी लौटाता है?
चार्ली पार्कर

जवाबों:


1241

random.shuffleकार्य करना चाहिए। यहां एक उदाहरण दिया गया है, जहां वस्तुएं सूचीबद्ध हैं:

from random import shuffle
x = [[i] for i in range(10)]
shuffle(x)

# print(x)  gives  [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]
# of course your results will vary

ध्यान दें कि फेरबदल जगह में काम करता है , और कोई नहीं लौटाता है।


1
@ सियोखूनले न। यह एक pseduo- यादृच्छिक संख्या जनरेटर है, जो जब संभव हो, ओएस से वास्तविक यादृच्छिकता के स्रोत द्वारा वरीयता प्राप्त होता है। सभी लेकिन क्रिप्टोग्राफी प्रयोजनों के लिए यह यादृच्छिक "पर्याप्त" है। इसे randomमॉड्यूल के प्रलेखन में विस्तार से रखा गया है ।
dimo414

2
एक नई सूची के लिए क्लोन का उपयोग करें
मोहम्मद महदी कूचायज़ादी

8
क्या कोई विकल्प है जो मूल सरणी को म्यूट नहीं करता है लेकिन एक नया शिल्ड सरणी लौटाता है?
चार्ली पार्कर

5
@CharlieParker: ऐसा नहीं है कि मुझे पता है। आप उपयोग random.sample(x, len(x))कर सकते हैं या बस एक प्रति और बना सकते हैं shufflelist.sortजिसके लिए एक समान मुद्दा है, अब वहां है list.sorted, लेकिन इसके लिए एक समान संस्करण नहीं है shuffle
टॉम 10

6
क्रिप्टो-सुरक्षित यादृच्छिकता के लिए @seokhonlee, from random import SystemRandomइसके बजाय का उपयोग करें ; जोड़ने cryptorand = SystemRandom()के लिए और परिवर्तन पंक्ति 3cryptorand.shuffle(x)
browly

115

जैसा कि आपने सीखा कि इन-प्लेस फेरबदल समस्या थी। मुझे भी अक्सर समस्या होती है, और अक्सर यह भी लगता है कि सूची को कॉपी करने के लिए कैसे भूल जाते हैं। का उपयोग करते हुए sample(a, len(a)), समाधान है का उपयोग कर len(a)नमूने का आकार के रूप में। पायथन प्रलेखन के लिए https://docs.python.org/3.6/library/random.html#random.sample देखें ।

यहां एक सरल संस्करण का उपयोग random.sample()किया गया है जो नई सूची के रूप में फेरबदल परिणाम देता है।

import random

a = range(5)
b = random.sample(a, len(a))
print a, b, "two list same:", a == b
# print: [0, 1, 2, 3, 4] [2, 1, 3, 4, 0] two list same: False

# The function sample allows no duplicates.
# Result can be smaller but not larger than the input.
a = range(555)
b = random.sample(a, len(a))
print "no duplicates:", a == list(set(b))

try:
    random.sample(a, len(a) + 1)
except ValueError as e:
    print "Nope!", e

# print: no duplicates: True
# print: Nope! sample larger than population

क्या कोई विकल्प है जो मूल सरणी को म्यूट नहीं करता है लेकिन एक नया शिल्ड सरणी लौटाता है?
चार्ली पार्कर

: बस सूची @CharlieParker कॉपी old = [1,2,3,4,5]; new = list(old); random.shuffle(new); print(old); print(new), (नई-पंक्तियों के साथ बदलें)
fjsj

old[:]सूची के लिए एक उथली प्रतिलिपि भी कर सकता है old
जिओ

sample()एक डेटा विश्लेषण प्रोटोटाइप के लिए विशेष रूप से उपयोगी है। sample(data, 2)एक पाइप लाइन के गोंद कोड को स्थापित करने के लिए, फिर इसे "चौड़ा" करना, चरण-वार, ऊपर तक len(data)
कैटरीन लेइनवेबर

58

मुझे भी कुछ समय लगा। लेकिन फेरबदल के लिए प्रलेखन बहुत स्पष्ट है:

जगह में फेरबदल सूची x ; कोई नहीं लौटा।

तो आपको नहीं करना चाहिए print(random.shuffle(b))। इसके बजाय करो random.shuffle(b)और फिर print(b)


44
#!/usr/bin/python3

import random

s=list(range(5))
random.shuffle(s) # << shuffle before print or assignment
print(s)

# print: [2, 4, 1, 3, 0]

31

यदि आप पहले से ही वैज्ञानिक (वित्तीय और वित्तीय अनुप्रयोगों के लिए बहुत लोकप्रिय) का उपयोग कर रहे हैं, तो आप अपने आप को एक आयात बचा सकते हैं।

import numpy as np    
np.random.shuffle(b)
print(b)

http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.shuffle.html


मुझे इस जवाब के बारे में क्या पसंद है कि मैं यादृच्छिक बीज को सुन्न में नियंत्रित कर सकता हूं। मुझे यकीन है कि यादृच्छिक मॉड्यूल में ऐसा करने का एक तरीका है लेकिन अभी मेरे लिए यह स्पष्ट नहीं है ... जिसका अर्थ है कि मुझे और अधिक पढ़ने की आवश्यकता है।
वनबंतम

25
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

यह मेरे लिए ठीक काम करता है। यादृच्छिक विधि सेट करना सुनिश्चित करें।


फिर भी मेरे लिए काम नहीं करता है, संपादित प्रश्न में मेरा उदाहरण कोड देखें।
उत्कर्ष

4
दूसरा पैरामीटर random.random में चूक करता है। इसे छोड़ना पूरी तरह से सुरक्षित है।
cbare

3
@alvas random.shuffle (a) किसी भी चीज़ को वापस नहीं करता है अर्थात यह कोई नहीं लौटाता है। इसलिए आपको रिटर्न नॉट वैल्यू चेक करना होगा।
sonus21

15

यदि आपके पास कई सूचियाँ हैं, तो आप क्रमपरिवर्तन को परिभाषित करना चाहते हैं (जिस तरह से आप सूची में फेरबदल करते हैं / सूची में वस्तुओं को फिर से व्यवस्थित करते हैं) और फिर इसे सभी सूचियों पर लागू करते हैं:

import random

perm = list(range(len(list_one)))
random.shuffle(perm)
list_one = [list_one[index] for index in perm]
list_two = [list_two[index] for index in perm]

ऊबड़ / खुरपी

यदि आपकी सूचियाँ सुस्पष्ट सरणियाँ हैं, तो यह सरल है:

import numpy as np

perm = np.random.permutation(len(list_one))
list_one = list_one[perm]
list_two = list_two[perm]

MPU

मैंने छोटी उपयोगिता पैकेज बनाया है mpuजिसमें consistent_shuffleफ़ंक्शन है:

import mpu

# Necessary if you want consistent results
import random
random.seed(8)

# Define example lists
list_one = [1,2,3]
list_two = ['a', 'b', 'c']

# Call the function
list_one, list_two = mpu.consistent_shuffle(list_one, list_two)

ध्यान दें कि mpu.consistent_shuffleएक मनमानी संख्या तर्क लेती है। तो आप इसके साथ तीन या अधिक सूचियों में फेरबदल भी कर सकते हैं।


10
from random import random
my_list = range(10)
shuffled_list = sorted(my_list, key=lambda x: random())

यह विकल्प कुछ अनुप्रयोगों के लिए उपयोगी हो सकता है जहां आप ऑर्डर करने वाले फ़ंक्शन को स्वैप करना चाहते हैं।


यह भी ध्यान दें कि इसके लिए धन्यवाद sorted, यह एक कार्यात्मक फेरबदल है (यदि आप उस तरह के हैं)।
इनामाथी

1
यह वास्तव में Timsort की स्थिरता के कारण मूल्यों को यादृच्छिक रूप से वितरित नहीं करता है। (एक ही कुंजी वाले मानों को उनके मूल क्रम में छोड़ दिया गया है।) संपादित करें: मुझे लगता है कि इससे कोई फर्क नहीं पड़ता क्योंकि 64-बिट फ़्लोट्स के साथ टकराव का जोखिम काफी कम है।
मतीन उल्हाक

10

कुछ मामलों में जब संख्यात्मक सरणियों का उपयोग करते हैं, random.shuffleतो सरणी में बनाए गए डुप्लिकेट डेटा का उपयोग करते हुए ।

एक विकल्प का उपयोग करना है numpy.random.shuffle। यदि आप पहले से ही सुन्न के साथ काम कर रहे हैं, तो यह सामान्य से अधिक पसंदीदा तरीका है random.shuffle

numpy.random.shuffle

उदाहरण

>>> import numpy as np
>>> import random

का उपयोग कर random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [1, 2, 3],
       [4, 5, 6]])

का उपयोग कर numpy.random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> np.random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [7, 8, 9],
       [4, 5, 6]])

1
इसके अलावा, numpy.random.permutationब्याज की हो सकती है: stackoverflow.com/questions/15474159/shuffle-vs-permute-numpy
गॉर्डन बीन

क्या आपके पास random.shuffle का उपयोग करते समय किसी सरणी में डुप्लिकेट किए गए डेटा का उदाहरण है?
nurettin

हाँ - यह मेरे उत्तर में शामिल है। "उदाहरण" नामक अनुभाग देखें। ;)
गॉर्डन बीन

कोई बात नहीं, मैंने तीन तत्व देखे और सोचा कि यह एक ही है। अच्छी खोज
19

1
random.shuffleप्रलेखन चिल्लाना चाहिए खस्ता सरणियों के साथ उपयोग न करें
शीतकालीन

10

एक-लाइनर्स के लिए, random.sample(list_to_be_shuffled, length_of_the_list)एक उदाहरण के साथ उपयोग करें :

import random
random.sample(list(range(10)), 10)

आउटपुट: [२, ९, 9, 9, ३, ०, ४, १, ६, ५]


6

oo प्रिंट फुक (फू) ’'फू’ से पुकारे जाने पर' फंक ’का रिटर्न वैल्यू प्रिंट करेगा। 'फेरबदल' में हालांकि इसकी वापसी प्रकार के रूप में कोई नहीं है, क्योंकि सूची को जगह में संशोधित किया जाएगा, इसलिए यह कुछ भी नहीं प्रिंट करता है। युक्ति:

# shuffle the list in place 
random.shuffle(b)

# print it
print(b)

यदि आप कार्यात्मक प्रोग्रामिंग शैली में अधिक हैं, तो आप निम्न आवरण कार्य करना चाहते हैं:

def myshuffle(ls):
    random.shuffle(ls)
    return ls

2
चूंकि यह सूची का संदर्भ देता है, इसलिए मूल संशोधित हो जाता है। आप डीप
shivram.ss

@ shivram.ss इस मामले में, आप कुछ ऐसा चाहते हैं, random.sample(ls, len(ls))यदि आप वास्तव में उस मार्ग से नीचे जाना चाहते हैं।
अर्क ग्यारह

4

कोई एक फ़ंक्शन को परिभाषित कर सकता है shuffled( sortबनाम समान अर्थ में sorted)

def shuffled(x):
    import random
    y = x[:]
    random.shuffle(y)
    return y

x = shuffled([1, 2, 3, 4])
print x

3
import random

class a:
    foo = "bar"

a1 = a()
a2 = a()
a3 = a()
a4 = a()
b = [a1,a2,a3,a4]

random.shuffle(b)
print(b)

shuffle जगह में है, इसलिए परिणाम को प्रिंट न करें, जो है None, लेकिन सूची।


1

आप इसके लिए जा सकते हैं:

>>> A = ['r','a','n','d','o','m']
>>> B = [1,2,3,4,5,6]
>>> import random
>>> random.sample(A+B, len(A+B))
[3, 'r', 4, 'n', 6, 5, 'm', 2, 1, 'a', 'o', 'd']

यदि आप दो सूचियों पर वापस जाना चाहते हैं, तो आप इस लंबी सूची को दो में विभाजित करें।


1

आप एक फ़ंक्शन का निर्माण कर सकते हैं जो एक सूची को पैरामीटर के रूप में लेता है और सूची का एक फेरबदल संस्करण देता है:

from random import *

def listshuffler(inputlist):
    for i in range(len(inputlist)):
        swap = randint(0,len(inputlist)-1)
        temp = inputlist[swap]
        inputlist[swap] = inputlist[i]
        inputlist[i] = temp
    return inputlist

1
""" to shuffle random, set random= True """

def shuffle(x,random=False):
     shuffled = []
     ma = x
     if random == True:
         rando = [ma[i] for i in np.random.randint(0,len(ma),len(ma))]
         return rando
     if random == False:
          for i in range(len(ma)):
          ave = len(ma)//3
          if i < ave:
             shuffled.append(ma[i+ave])
          else:
             shuffled.append(ma[i-ave])    
     return shuffled

एक छोटा सा परिचय या स्पष्टीकरण सहायक होगा?
kacase

यह कार्य गतिविधि को बदलने के लिए सहायक है, कल्पना करें कि आपको तीन बार संख्याओं की सूची में फेरबदल करना है और तीन बार में आपको यादृच्छिक फेरबदल की आवश्यकता होती है, तो यादृच्छिक तर्क को सही पर फिर से चालू करें यदि आपको यादृच्छिकता की आवश्यकता नहीं है और आप चाहते हैं उसी फेरबदल के आदेश को संरक्षित किया जाना है तो कोई बदलाव न करें, बस कोड चलाएं।
जोश अनिश

चूंकि कोई उपयोग मामला नहीं है, जहां इस फ़ंक्शन का कॉलर रनटाइम पर तय करेगा कि क्या वह यादृच्छिक या गैर-यादृच्छिक फेरबदल चाहता है, इस फ़ंक्शन को दो में विभाजित किया जाना चाहिए।
टूलबार

गैर-यादृच्छिक फेरबदल क्या करना चाहिए इसका कोई विवरण नहीं है। (एक स्पर्शरेखा पर, यह एक सवाल का जवाब नहीं है, इसलिए यह स्टैक ओवरफ्लो के उद्देश्य की पूर्ति नहीं करता है।)
टूलोपर

1

आप या तो फेरबदल या नमूना का उपयोग कर सकते हैं। जो दोनों यादृच्छिक मॉड्यूल से आते हैं।

import random
def shuffle(arr1):
    n=len(arr1)
    b=random.sample(arr1,n)
    return b

या

import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1

0

सुनिश्चित करें कि आप अपनी स्रोत फ़ाइल को यादृच्छिक संख्या में नाम नहीं दे रहे हैं, और यह कि आपके काम करने वाली निर्देशिका में कोई फ़ाइल नहीं है, जिसे random.pyc कहा जाता है .. या तो आपके प्रोग्राम को अजगर यादृच्छिक यादृच्छिक मॉड्यूल के बजाय आपके स्थानीय random.py फ़ाइल को आयात करने और आयात करने का कारण बन सकता है। ।


0
def shuffle(_list):
    if not _list == []:
        import random
        list2 = []
        while _list != []:
            card = random.choice(_list)
            _list.remove(card)
            list2.append(card)
        while list2 != []:
            card1 = list2[0]
            list2.remove(card1)
            _list.append(card1)
        return _list

आप यादृच्छिक मॉड्यूल का उपयोग नहीं करना चाहते हैं, तो यह कार्य आप मदद कर सकते हैं
Pogramist

यह समाधान केवल क्रिया नहीं है, लेकिन अक्षम (रनटाइम सूची आकार के वर्ग के लिए आनुपातिक है)।
टूलबार

दूसरे लूप को प्रतिस्थापित किया जा सकता है _list.extend(list2), जो अधिक रसीला और अधिक कुशल है।
टूलबार

एक पायथन फ़ंक्शन जो एक पैरामीटर को संशोधित करता है, उसे कभी भी परिणाम नहीं देना चाहिए। यह सिर्फ एक सम्मेलन है, लेकिन एक उपयोगी है: लोगों को अक्सर उन सभी कार्यों के कार्यान्वयन को देखने के लिए समय की कमी होती है, जिन्हें वे कहते हैं, इसलिए जो कोई भी आपके फ़ंक्शन का नाम देखता है और उसके पास फ़ंक्शन देखने के लिए बहुत आश्चर्य होगा इसके पैरामीटर को अपडेट करें।
टूलबार


-1

फेरबदल की प्रक्रिया "प्रतिस्थापन के साथ" है , इसलिए प्रत्येक आइटम की घटना बदल सकती है! कम से कम जब आपकी सूची में आइटम भी सूची में हैं।

उदाहरण के लिए,

ml = [[0], [1]] * 10

उपरांत,

random.shuffle(ml)

[०] की संख्या ९ या] हो सकती है, लेकिन ठीक १० नहीं।


-1

योजना: भारी उठाने के लिए एक पुस्तकालय पर भरोसा किए बिना फेरबदल लिखें। उदाहरण: तत्व 0 से शुरू होने वाली सूची से गुजरें; इसके लिए एक नई यादृच्छिक स्थिति ढूंढें, 6 कहें, 6 में 0 का मान और 6 में 6 का मान। तत्व 1 पर जाएं और इस प्रक्रिया को दोहराएं, और इसी तरह बाकी सूची के माध्यम से

import random
iteration = random.randint(2, 100)
temp_var = 0
while iteration > 0:

    for i in range(1, len(my_list)): # have to use range with len()
        for j in range(1, len(my_list) - i):
            # Using temp_var as my place holder so I don't lose values
            temp_var = my_list[i]
            my_list[i] = my_list[j]
            my_list[j] = temp_var

        iteration -= 1

आप इस तरह से अजगर में चर स्वैप कर सकते हैं:my_list[i], my_list[j] = my_list[j], my_list[i]
करोलिस रिसेलिस

-2

यह बढ़िया काम करता है। मैं इसे सूची वस्तुओं के रूप में यहां कार्य कर रहा हूं:

    from random import shuffle

    def foo1():
        print "foo1",

    def foo2():
        print "foo2",

    def foo3():
        print "foo3",

    A=[foo1,foo2,foo3]

    for x in A:
        x()

    print "\r"

    shuffle(A)
    for y in A:
        y()

यह प्रिंट करता है: foo1 foo2 foo3 foo2 foo3 foo1 (अंतिम पंक्ति में फॉक्स का एक यादृच्छिक क्रम है)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.