2013-08-16 16 views
112

Belirtilen listeden bazı öğelerini seçerek indekslerini bilmeliyim. Belirtilen listeden [-2, 1, 5, 3, 8, 5, 6] dizin 1, 2, 5 ile eleman içeren yeni bir liste oluşturmak istediğimi varsayalım. Ne yaptım:Endekslerini bilen çok sayıda listeye erişme

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

Bunu yapmak için daha iyi bir yolu var mı? C = a [b] gibi bir şey?

+0

, burada başka bir çözüm buldu . Henüz test etmedim, ama http://code.activestate.com/recipes/577953-get-multiple-elements-from-a-list/ –

+0

ile ilgilendiğiniz zaman buraya gönderebileceğimi düşünüyorum. soruda belirtilen aynı çözüm, ancak bir lambda fonksiyonuna sarılmıştır. –

+0

Olası kopyası [python'daki bir listeden öğeler nasıl çıkarılır?] (Https://stackoverflow.com/questions/2621674/how-to-extract-elements-from-a-list-in-python) – jdhao

cevap

113

Sen operator.itemgetter kullanabilirsiniz:

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

Yoksa kullanabilirsiniz 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] 

Ama gerçekten, mevcut çözümün gayet iyi. Muhtemelen hepsinden en iyisi.

+14

+1 'c = [a [i]' nin b için] olduğunu belirtmek için gayet iyi. B öğesinin 2 öğeden daha az olması durumunda, 'itemgetter' çözümünün aynı şeyi yapmayacağını unutmayın. – flornquake

+0

** Side ** ** Not **: Çok işlemlerde çalışırken _itemgetter_'ın kullanılması işe yaramıyor. Numpy çok süreçte harika çalışıyor. –

+0

Ek yorum, 'a [b]' sadece ** ** bir ** numpy ** dizisidir, yani bir numpy işleviyle oluşturduğunuzda çalışır. –

22

Alternatifler:

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

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

Cevabım numpy veya python koleksiyonlarını kullanmaz. aşağıdaki gibi unsurlar olacaktır bulmak için

Tek önemsiz yolu:

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

Dezavantajı: Bu yöntem büyük listeler için çalışmayabilir. Daha büyük listeler için numpy kullanılması önerilir. Aşağıdaki girişi kullanarak

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] 

: beş verilen cevapların uygulama süresini karşılaştıran

+3

"a" yinelemeye gerek yok. [a [i] için b] '' – falsetru

+0

Bu yöntem, başka bir durumda bile çalışmaz. Ya a'nın 5 tane daha varsa? – TerryA

+0

IMO, [set] (https://docs.python.org/3/tutorial/datastructures.html#sets) – sirgogo

3

temel ve çok kapsamlı testler

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

basit piton loop lambda işlem A 'ile hızlı close ikincisi, mapIndexValues ​​ve getIndexValues, numpy dizisi ile listelerin dönüştürülmesinden sonra, numpy yöntemiyle oldukça yavaş bir şekilde benzerdi. Veriler zaten numpy dizilerinde numpyIndexValues ​​yöntemi ile numpyIndexValues ​​yöntemidir. .dizinin kaldırılması en hızlıdır.

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 
+0

kullanarak bu tür kesişme yapmak için daha hızlı Python yorumlayıcısının ne kullandığını bilmiyorum ama ilk yöntem ' numpyIndexValues', 'a',' '' '' '' '' '' 'türünden '' çalışmadığından dolayı çalışmaz. Önce 'a', 'b' 'numpy.ndarrays' 'ı dönüştürmeyi düşündüğünüzü tahmin ediyorum. – strpeter

+0

@strpeter Evet, elmaları elmalarla karşılaştırmıyordum, numpyIndexValues ​​için test durumunda girdi olarak numpy dizileri oluşturmuştum. Bunu şimdi düzelttim ve hepsi aynı listeleri girdi olarak kullanıyor. –

2

bu zaten kabul edilmiştir eminim:

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

Ya endeksleri ise daha da basit: b indekslerinin miktarı küçük ve sabit ise, tek tıpkı sonucu yazabiliriz sabittir ...

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

Ardışık bir aralık dizisi varsa ...

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

Bana şunu hatırladığın için teşekkür ederim: [a] + [b] = [a, b] ' – onewhaleid

1

Başka bir çözüm pandalar Serisi yoluyla olabilir:

import pandas as pd 

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

Ardından tekrar isterseniz bir listeye c dönüştürebilirsiniz: bu arada

c = list(c)