सूची के कई तत्वों को उनके सूचकांक को जानकर


232

मुझे दिए गए सूची से कुछ तत्वों को चुनने की जरूरत है, उनके सूचकांक को जानना। मान लें कि मैं एक नई सूची बनाना चाहता हूं, जिसमें दिए गए सूची [-2, 1, 5, 3, 8, 5, 6] से सूचकांक 1, 2, 5 के साथ तत्व शामिल हैं। मैंने क्या किया है:

a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]

क्या इसे करने का कोई बेहतर तरीका है? c = a [b] जैसा कुछ?


1
वैसे, मुझे यहां एक और समाधान मिला। मैंने अभी तक इसका परीक्षण नहीं किया है, लेकिन मुझे लगता है कि मैं इसे एक बार यहां पोस्ट कर सकता हूं जब आप रुचि रखते हैं। code.activestate.com/recipes/…
hoang tran

यह वही प्रश्न है जो प्रश्न में उल्लिखित है, लेकिन एक lambdaफ़ंक्शन में लिपटा हुआ है ।
डेरेहम

जवाबों:


218

आप उपयोग कर सकते हैं operator.itemgetter:

from operator import itemgetter 
a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
print(itemgetter(*b)(a))
# Result:
(1, 5, 5)

या आप numpy का उपयोग कर सकते हैं :

import numpy as np
a = np.array([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
print(list(a[b]))
# Result:
[1, 5, 5]

लेकिन वास्तव में, आपका वर्तमान समाधान ठीक है। यह शायद उन सभी में से सबसे साफ है।


35
+1 का उल्लेख करने के लिए जो c = [a[i] for i in b]पूरी तरह से ठीक है। ध्यान दें कि itemgetterबी 2 तत्वों से कम होने पर समाधान एक ही काम नहीं करेगा।
flornquake

साइड नोट : बहु प्रक्रिया में काम करते समय आइटम का उपयोग करना काम नहीं करता है। Numpy मल्टी-प्रक्रिया में महान काम करता है।
लाइर मैगन

3
अतिरिक्त टिप्पणी, केवल तभीa[b] काम करती है , जब आप एक अंको वाली सारणी बनाते हैं, अर्थात आप इसे एक संख्यात्मक कार्य के साथ बनाते हैं। a
लुडविग झोउ

मैंने गैर-खस्ता विकल्पों को बेंचमार्क किया है और आइटम को सबसे तेज़, यहां तक ​​कि सबसे तेज से भी छोटा प्रतीत होता है, जहां पाइरेथंस के अंदर वांछित इंडेक्स टाइप करने की तुलना में पायथन 3.44 का उपयोग कर रहा है
रागर्डनर

@ Cit2077, क्या आप अपने द्वारा वर्णित वाक्यविन्यास का उदाहरण दे सकते हैं?
अलंकालविटि 19

47

विकल्प:

>>> map(a.__getitem__, b)
[1, 5, 5]

>>> import operator
>>> operator.itemgetter(*b)(a)
(1, 5, 5)

पहले एक अच्छा है क्योंकि आप build-in
सिल्गन

समस्या w / पहला है कि __getitem__आइटम के प्रकार को कैसे मैप किया जाए , यह समझ में नहीं आता है? map(type(a.__getitem__), b)
अलंकालविटि

@alancalvitti, lambda x: type(a.__getitem__(x)), b। इस मामले में उपयोग [..]करना अधिक कॉम्पैक्ट है:lambda x: type(a[x]), b
falsetru

9

एक और उपाय पांडा श्रृंखला के माध्यम से हो सकता है:

import pandas as pd

a = pd.Series([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
c = a[b]

यदि आप चाहें तो आप सी को एक सूची में बदल सकते हैं:

c = list(c)

7

पांच आपूर्ति किए गए उत्तरों के निष्पादन समय की तुलना में बुनियादी और बहुत व्यापक परीक्षण नहीं:

def numpyIndexValues(a, b):
    na = np.array(a)
    nb = np.array(b)
    out = list(na[nb])
    return out

def mapIndexValues(a, b):
    out = map(a.__getitem__, b)
    return list(out)

def getIndexValues(a, b):
    out = operator.itemgetter(*b)(a)
    return out

def pythonLoopOverlap(a, b):
    c = [ a[i] for i in b]
    return c

multipleListItemValues = lambda searchList, ind: [searchList[i] for i in ind]

निम्नलिखित इनपुट का उपयोग कर:

a = range(0, 10000000)
b = range(500, 500000)

सरल अजगर पाश लैंबडा ऑपरेशन के साथ सबसे तेज था, एक दूसरा सेकंड, mapIndexValues ​​और getIndexValues ​​लगातार खाँसी विधि के साथ सूचियों को बदलने के बाद काफी धीमी विधि के साथ लगातार समान थे। तेज।

numpyIndexValues -> time:1.38940598 (when converted the lists to numpy arrays)
numpyIndexValues -> time:0.0193445 (using numpy array instead of python list as input, and conversion code removed)
mapIndexValues -> time:0.06477512099999999
getIndexValues -> time:0.06391049500000001
multipleListItemValues -> time:0.043773591
pythonLoopOverlap -> time:0.043021754999999995

मैं नहीं जानता कि पायथन इंटरप्रेटर का आप क्या उपयोग करते हैं लेकिन पहली विधि numpyIndexValuesकाम नहीं करती है a, bप्रकार की हैं range। मैं अनुमान लगा रहा हूँ कि आप परिवर्तित बयान a, bकरने के लिए numpy.ndarraysपहली बार?
स्ट्रेटर

@strpeter हाँ, मैं सेब के साथ सेब की तुलना नहीं कर रहा था, मैंने टेस्टी केस में इनपुट के रूप में संख्यात्मक सरणियों का निर्माण किया था। मैंने इसे अभी ठीक कर लिया है और सभी इनपुट के समान सूचियों का उपयोग करते हैं।
डॉन स्मिथे

4

मुझे यकीन है कि यह पहले ही माना जा चुका है: यदि बी में सूचकांकों की मात्रा छोटी और स्थिर है, तो कोई भी इस तरह से परिणाम लिख सकता है:

c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]]

या सरल भी अगर सूचकांक खुद स्थिरांक हैं ...

c = [a[1]] + [a[2]] + [a[5]]

या अगर सूचकांकों की एक निरंतर सीमा है ...

c = a[1:3] + [a[5]]

मुझे याद दिलाने के लिए धन्यवाद कि[a] + [b] = [a, b]
onewhaleid


1

मेरा जवाब सुन्न या अजगर संग्रह का उपयोग नहीं करता है।

तत्वों को खोजने का एक तुच्छ तरीका इस प्रकार होगा:

a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
c = [i for i in a if i in b]

दोष: यह विधि बड़ी सूचियों के लिए काम नहीं कर सकती है। बड़ी सूचियों के लिए numpy का उपयोग करने की सिफारिश की जाती है।


5
पुनरावृति की आवश्यकता नहीं है a[a[i] for i in b]
falsetru

1
यह विधि किसी अन्य मामले में भी काम नहीं करती है। अगर aइसमें 5 और हो तो क्या होगा?
टेरीया


यदि आप IndexErrors के बारे में चिंतित हैं यदि b की संख्या है जो आकार से अधिक है, तो प्रयास करें[a[i] if i<len(a) else None for i in b]
576i

0

स्टेटिक इंडेक्स और छोटी सूची?

यह मत भूलो कि यदि सूची छोटी है और अनुक्रमित नहीं बदलते हैं, जैसा कि आपके उदाहरण में, कभी-कभी सबसे अच्छी बात अनुक्रम अनपैक का उपयोग करना है :

_,a1,a2,_,_,a3,_ = a

प्रदर्शन बहुत बेहतर है और आप कोड की एक पंक्ति भी बचा सकते हैं:

 %timeit _,a1,b1,_,_,c1,_ = a
10000000 loops, best of 3: 154 ns per loop 
%timeit itemgetter(*b)(a)
1000000 loops, best of 3: 753 ns per loop
 %timeit [ a[i] for i in b]
1000000 loops, best of 3: 777 ns per loop
 %timeit map(a.__getitem__, b)
1000000 loops, best of 3: 1.42 µs per loop

0

पाइथोनिक तरीके की तरह:

c = [x for x in a if a.index(x) in b]

2
मैं कहूंगा कि यह ओपी के उदाहरण की तुलना में कम "पायथोनिक" है - आप उनके O(n)समाधान को एक O(n^2)समाधान में बदलने में कामयाब रहे हैं जबकि कोड की लंबाई भी लगभग दोगुनी हो गई है। आप यह भी नोट करना चाहेंगे कि दृष्टिकोण विफल हो जाएगा यदि सूची में ऑब्जेक्ट फ़ज़ी या आंशिक समानता होंगे, जैसे यदि aशामिल हैं float('nan'), तो यह हमेशा ए होगा ValueError
ब्रायन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.