2010-09-09 17 views
14

मेरे सवाल है, मैं निम्नलिखित की तरह एक सूची है:पायथन बहुआयामी सूची .. एक आयाम कैसे पकड़ें?

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

कैसे मैं प्रत्येक sublist की पहली प्रविष्टि प्राप्त होगा?

मैं जानता हूँ कि मैं यह कर सकता है:

newList = [] 
for entry in someList: 
    newList.append(entry[0]) 

जहां newList होगा:

[0, 3, 6] 

लेकिन वहाँ की तरह कुछ करने के लिए एक तरीका है:

newList = someList[:][0] 

?

संपादित करें:

क्षमता बहुत बड़ी चिंता का विषय है। मैं वास्तव में 300000 से अधिक प्रविष्टियों

है कि एक सूची के माध्यम से जा रहा हूँ

उत्तर

17

संपादित करें: यहां कुछ वास्तविक संख्याएं हैं! izip, सूची समझ, और numpy ऐसा करने के तरीके सभी एक ही गति के बारे में हैं।

# zip 
>>> timeit.timeit("newlist = zip(*someList)[0]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10) 
1.4984046398561759 

# izip 
>>> timeit.timeit("newlist = izip(*someList).next()", setup = "someList = range(1000000), range(1000000), range(1000000)]; from itertools import izip", number = 10) 
2.2186223645803693e-05 

# list comprehension 
>>> timeit.timeit("newlist = [li[0] for li in someList]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10) 
1.4677040212518477e-05 

# numpy 
>>> timeit.timeit("newlist = someList[0,:]", setup = "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)])", number = 10) 
6.6217344397045963e-05 
>>> 

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

>>> import numpy as np 
>>> foo = np.array([[0,1,2],[3,4,5],[6,7,8]]) 
>>> foo[:,0] 
array([0, 3, 6]) 

तुम भी स्थानांतरित कर सकते हैं ...

>>> foo.transpose() 
array([[0, 3, 6], 
     [1, 4, 7], 
     [2, 5, 8]]) 

... n आयामी सरणियों के साथ काम ...

>>> foo = np.zeros((3,3,3)) 
>>> foo 
array([[[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]], 

     [[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]], 

     [[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]]) 
>>> foo[0,...] 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 

..do कुशल रेखीय बीजगणित ...

>>> foo = no.ones((3,3)) 
>>> np.linalg.qr(foo) 
(array([[-0.57735027, 0.81649658, 0.  ], 
     [-0.57735027, -0.40824829, -0.70710678], 
     [-0.57735027, -0.40824829, 0.70710678]]), array([[ -1.73205081e+00, -1. 
73205081e+00, -1.73205081e+00], 
     [ 0.00000000e+00, -1.57009246e-16, -1.57009246e-16], 
     [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]])) 

... और मूल रूप से anything that Matlab can करें।

+0

वाह, बहुत बहुत धन्यवाद। यह अन्य समाधानों की तुलना में सुपर फास्ट है। अगर मैं +100000 कर सकता हूं तो मैं – Richard

+1

@ रिचर्ड: यह निर्भर करता है ... सूची जितनी बड़ी होगी, उतनी ही बेहतर होगी कि इज़िप और सूची समझ समाधान सुस्त के खिलाफ प्रदर्शन करते हैं, क्योंकि वे मैट्रिक्स प्रविष्टियों के विशाल बहुमत पर विचार नहीं करते हैं। –

+2

@ जेलीबीन: मुझे संदेह है कि ... numpy वास्तव में काफी अच्छी तरह अनुकूलित है। मुझे लगता है कि यह कहना सुरक्षित है कि एक साधारण कॉलम-वार स्लाइस पूरे मैट्रिक्स को नहीं पढ़ेगा। (हालांकि मैं निश्चित रूप से गलत हो सकता हूं, मुझे सी कार्यान्वयन के विवरणों को नहीं पता है।) असल में, मुझे लगता है कि 'numpy' को एक बड़ी सूची के साथ * बेहतर * करना चाहिए, क्योंकि पायथन के मूल' सूची 'प्रकार के उपरांत शुरू होते हैं कुल योग। लेकिन निश्चित रूप से, पता लगाने के लिए केवल एक ही रास्ता है! – katrielalex

8
zip(*someList)[0] 

संपादित करें:

पुनरावर्ती की टिप्पणी के जवाब में: एक भी बेहतर प्रदर्शन के लिए उपयोग कर सकते हैं

from itertools import izip 
izip(*someList).next() 

कुछ समय विश्लेषण:

python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = zip(*someList)[0]" 
10 loops, best of 3: 498 msec per loop 
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; from itertools import izip; newlist = izip(*someList).next()" 
10 loops, best of 3: 111 msec per loop 
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = [li[0] for li in someList]" 
10 loops, best of 3: 110 msec per loop 

तो izip और एक ही लीग में सूची समझ खेलते हैं।

बेशक सूची की समझ अधिक लचीला है जब आपको 0 से अधिक सूचकांक की आवश्यकता होती है, और यह अधिक स्पष्ट है।

EDIT2:

भी numpy समाधान के रूप में तेजी से (लेकिन मैं एक गैर प्रतिनिधि उदाहरण चुना है हो सकता है) नहीं है:

python -m timeit "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)]); newList = someList[:,0]" 
10 loops, best of 3: 551 msec per loop 
+0

यदि कुछ सूची बड़ी है, तो यह अन्य सभी स्तंभों को जोड़कर भी बहुत अनावश्यक काम करने जा रहा है। – recursive

10

एक list comprehension के लिए बिल्कुल सही मामला:

[sublist[0] for sublist in someList] 

चूंकि दक्षता एक प्रमुख चिंता है, यह zip दृष्टिकोण से बहुत तेज होगी। क्या आप परिणाम के साथ कर रहे हैं निर्भर करता है, आप जनरेटर अभिव्यक्ति दृष्टिकोण का उपयोग करके और भी अधिक दक्षता प्राप्त करने में सक्षम हो सकता है:

(sublist[0] for sublist in someList) 

ध्यान दें कि यह एक सूची के बजाय एक जनरेटर रिटर्न हालांकि, ऐसा नहीं हो सकता है में अनुक्रमित

संबंधित मुद्दे