यादृच्छिक संख्याओं की सूची को दो के सेट में तोड़ने का सबसे तेज़ तरीका क्या होगा, वैकल्पिक रूप से प्रत्येक जोड़ी को फ़्लिप करना? उदाहरण के लिए:

pleatedTuple=(0, 1, 3, 2, 4, 5, 7, 6, 8, 9)

मुझे एक ऑपरेशन में क्या चाहिए:

flatPairs=[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]

आइटम यादृच्छिक एकल अंक होंगे, मैंने केवल उन्हें पठनीयता के लिए अनुक्रमिक बनाया है। मुझे इनमें से हजारों को एक बार में करने की जरूरत है इसलिए गति प्राथमिकता है। पायथन 3.6.4।

किसी भी विचार के लिए धन्यवाद, मैं इससे स्तब्ध हूं।

4
Gnarlodious 29 मार्च 2018, 05:40

3 जवाब

सबसे बढ़िया उत्तर

विकल्प 1
जब तक यह जोड़े है, हम बात कर रहे हैं, आइए सूची समझने की कोशिश करें:

flatPairs = [
    [x, y] if i % 2 == 0 else [y, x] for i, (x, y) in enumerate(
        zip(pleatedTuple[::2], pleatedTuple[1::2])
    )
]

आप इसे लूप का उपयोग करके स्क्रैच से भी बना सकते हैं:

flatPairs = []
for i, (x, y) in enumerate(zip(pleatedTuple[::2], pleatedTuple[1::2])):
    if i % 2 == 0:
        flatPairs.append([x, y])
    else:
        flatPairs.append([y, x])
print(flatPairs)
[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]

विकल्प 2
नेड बैचेल्डर के चंकिंग सबरूटीन chunks का उपयोग करें और प्रत्येक वैकल्पिक सबलिस्ट को फ्लिप करें:

# https://stackoverflow.com/a/312464/4909087
def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

chunks पर कॉल करें और जोड़ियों की सूची प्राप्त करने के लिए लौटे जनरेटर को समाप्त करें:

flatPairs = list(chunks(pleatedTuple, n=2))

अब, हर दूसरे जोड़े को एक लूप से उलट दें।

for i in range(1, len(flatPairs), 2):
    flatPairs[i] = flatPairs[i][::-1]
print(flatPairs)
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

ध्यान दें कि इस मामले में, परिणाम टुपल्स की एक सूची है।


प्रदर्शन
(केवल मेरे उत्तरों में से)
मुझे प्रदर्शन में दिलचस्पी है, इसलिए मैंने अपने उत्तरों को समय देने का फैसला किया है:

# Setup
pleatedTuple = tuple(range(100000))    
# List comp
21.1 ms ± 1.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)    
# Loop
20.8 ms ± 1.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# chunks
26 ms ± 2.19 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

अधिक प्रदर्शन के लिए, आप chunks जनरेटर को अधिक प्रदर्शन करने वाले विकल्प से बदल सकते हैं:

flatPairs = list(zip(pleatedTuple[::2], pleatedTuple[1::2]))

और फिर आवश्यकतानुसार एक लूप के साथ उल्टा करें। इससे समय काफी कम हो जाता है:

13.1 ms ± 994 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

एक 2x स्पीडअप, ओह! हालांकि सावधान रहें, यह लगभग उतना ही मेमोरी कुशल नहीं है जितना कि जनरेटर होगा ...

5
cs95 29 मार्च 2018, 03:01

आप इसे numpy में कर सकते हैं:

>>> pleatedTuple=(0, 1, 3, 2, 4, 5, 7, 6, 8, 9)
>>> pleatedArray = np.array(pleatedTuple)
>>> flat2D = pleatedArray.reshape(5,2)
>>> flat2D[1::2] = np.flip(pleated2D[1::2], axis=1)

बेशक यह संभवतः टुपल्स और सरणियों के बीच परिवर्तित होने में उतना ही समय बर्बाद करने वाला है क्योंकि यह पायथन के बजाय सुन्न में एक छोटा लूप करने से बचाता है। (एक त्वरित परीक्षण से, उदाहरण के आकार में Coldspeed's Option 2 जितना लंबा समय लगता है, और पकड़ में नहीं आता जब तक आप बहुत अधिक, बहुत लंबे टुपल्स तक नहीं पहुंच जाते, और आपके पास छोटे टुपल्स का एक गुच्छा होता है, कुछ विशाल वाले नहीं।)

लेकिन अगर आप गति से चिंतित हैं, तो स्पष्ट बात यह है कि इन हजारों प्लीटेड टुपल्स को एक विशाल सुपीरियर एरे में डाल दिया जाता है और उन सभी को एक ही बार में कर दिया जाता है, और फिर यह शायद बहुत तेज हो जाएगा। (फिर भी, हम शायद इनमें से हजारों के लिए मिलीसेकंड बचाने की बात कर रहे हैं।)

1
abarnert 29 मार्च 2018, 03:07

आप मानक समूहीकरण मुहावरे का उपयोग कर सकते हैं और इसे लंबाई के साथ ज़िप कर सकते हैं:

>>> by_pairs_index = zip(range(len(pleatedTuple)), *[iter(pleatedTuple)]*2)
>>> [[b, a] if i%2 else [a,b] for i,a,b in by_pairs_index]
[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]

यदि प्रदर्शन महत्वपूर्ण है, तो आप अन्य तरीकों पर विचार कर सकते हैं।

2
juanpa.arrivillaga 29 मार्च 2018, 02:46