Bir tuples listesindeki ilk elemanı nasıl edinebilirim?


178

İlk öğe kimliği ve diğer bir dize olduğu gibi aşağıdaki gibi bir liste var:

[(1, u'abc'), (2, u'def')]

Sadece aşağıdaki gibi bu tuples listesinden bir kimlik listesi oluşturmak istiyorum:

[1,2]

__inTamsayı değerlerinin bir listesi olması için bu listeyi kullanacağım .

Yanıtlar:


245
>>> a = [(1, u'abc'), (2, u'def')]
>>> [i[0] for i in a]
[1, 2]

68

Öğeleri ayırmak için zip işlevini kullanın:

>>> inpt = [(1, u'abc'), (2, u'def')]
>>> unzipped = zip(*inpt)
>>> print unzipped
[(1, 2), (u'abc', u'def')]
>>> print list(unzipped[0])
[1, 2]

Edit (@BradSolomon): Yukarıdaki zipliste bir liste döndüren Python 2.x için geçerlidir .

Python 3.x'te zipbir yineleyici döndürür ve aşağıdakiler yukarıdakine eşdeğerdir:

>>> print(list(list(zip(*inpt))[0]))
[1, 2]

bunun ayrı bir içe aktarmaya ihtiyacı var mı?
JuliandotNut

2
@JuliandotNut Hayır, yerleşik bir işlev. (Python
2.x'te

22

Bunun gibi birşey mi demek istedin?

new_list = [ seq[0] for seq in yourlist ]

Aslında, tuplenesnelerin bir listesi, kümelerin bir listesi değil (orijinal sorunuzun ima ettiği gibi). Aslında bir kümeler listesiyse, ilk öğe yoktur çünkü kümelerin sırası yoktur.

Burada düz bir liste oluşturdum çünkü genellikle 1 element tuples listesi oluşturmaktan daha yararlı görünüyor. Ancak, kolayca sadece değiştirerek 1 eleman dizilerini bir listesini oluşturabilirsiniz seq[0]ile (seq[0],).


Denedim. Bu hatayı veriyor:int() argument must be a string or a number, not 'QuerySet'
wasimbhalli

4
@wasimbhalli - int()benim çözümümde hiçbir yer yok, bu yüzden gördüğünüz istisnanın kodda daha sonra gelmesi gerekiyor.
mgilson

Soruyu güncelledim, bu listeyi daha sonra __inveri filtrelemek için kullanmam gerekiyor
wasimbhalli

nedir __in? - Verdiğiniz örnek girişe dayanarak, bu bir tamsayı listesi oluşturur. Ancak, tuples listeniz tamsayılarla başlamazsa, tamsayı elde edemezsiniz ve bunları tamsayı haline getirmeniz intveya ilk öğenizin neden bir tamsayıya dönüştürülemediğini anlamaya çalışmanız gerekir.
mgilson

Mu new_list = [ seq[0] for seq in yourlist if type(seq[0]) == int]iş?
pR0Ps

11

"Paket açma" kullanabilirsiniz:

>>> my_list = [(1, u'abc'), (2, u'def')]
>>> my_ids = [idx for idx, val in my_list]
>>> my_ids
[1, 2]

Yineleme zamanda her tuple paketlenmemiş ve onun değerleri değişkenlere ayarlanır idxve val.

>>> x = (1, u'abc')
>>> idx, val = x
>>> idx
1
>>> val
u'abc'

8

Bunun operator.itemgetteriçin bu.

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b
[1, 2]

itemgetterDeyim bir işlev döndürür belirttiğiniz öğenin dizinini döndürür. Yazmakla tamamen aynı

>>> b = map(lambda x: x[0], a)

Ama itemgetterbunun daha net ve daha açık olduğunu düşünüyorum .

Bu, kompakt sıralama ifadeleri yapmak için kullanışlıdır. Örneğin,

>>> c = sorted(a, key=operator.itemgetter(0), reverse=True)
>>> c
[(2, u'def'), (1, u'abc')]

7

Performans açısından bakıldığında, python3.X biçiminde.

  • [i[0] for i in a]ve list(zip(*a))[0]eşdeğerdir
  • onlar daha hızlı list(map(operator.itemgetter(0), a))

kod

import timeit


iterations = 100000
init_time = timeit.timeit('''a = [(i, u'abc') for i in range(1000)]''', number=iterations)/iterations
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = [i[0] for i in a]''', number=iterations)/iterations - init_time)
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = list(zip(*a))[0]''', number=iterations)/iterations - init_time)

çıktı

3.491014136001468e-05

3.422205176000717e-05


6

eğer tuples benzersizse o zaman bu işe yarayabilir

>>> a = [(1, u'abc'), (2, u'def')]
>>> a
[(1, u'abc'), (2, u'def')]
>>> dict(a).keys()
[1, 2]
>>> dict(a).values()
[u'abc', u'def']
>>> 

4
Bu siparişi kaybedecektir. Bununla birlikte ordereddict, işe yarayabilir .
Tim Tisdall

2 veya daha fazla tuple, çözümünüz işe yaramayacak ilk öğeye
sahipse

3

koştuğumda (yukarıda önerildiği gibi):

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b

geri dönmek yerine:

[1, 2]

Bunu iade olarak aldım:

<map at 0xb387eb8>

List () kullanmak zorunda olduğumu buldum:

>>> b = list(map(operator.itemgetter(0), a))

bu öneriyi kullanarak bir listeyi başarıyla döndürmek için. Bununla birlikte, bu çözümden memnunum, teşekkürler. (Spyder, iPython konsolu, Python v3.6 kullanılarak test edildi / çalıştırıldı)


3

Farklı yaklaşımların çalışma zamanlarını karşılaştırmanın yararlı olabileceğini düşünüyordum, bu yüzden bir ölçüt yaptım ( simple_benchmark kütüphanesini kullanarak )

I) 2 elemanlı tuples olan Benchmark resim açıklamasını buraya girin

Tuples'tan ilk öğeyi dizinlere göre seçmeyi 0beklediğiniz gibi, tam olarak 2 değer bekleyerek ambalajdan çıkarma çözümüne çok yakın en hızlı çözümdür

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()



@b.add_function()
def rakesh_by_index(l):
    return [i[0] for i in l]


@b.add_function()
def wayneSan_zip(l):
    return list(list(zip(*l))[0])


@b.add_function()
def bcattle_itemgetter(l):
     return list(map(operator.itemgetter(0), l))


@b.add_function()
def ssoler_upacking(l):
    return [idx for idx, val in l]

@b.add_function()
def kederrack_unpacking(l):
    return [f for f, *_ in l]



@b.add_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [(random.choice(range(100)), random.choice(range(100))) for _ in range(size)]


r = b.run()
r.plot()

II) 2 veya daha fazla eleman içeren tupllere sahip test resim açıklamasını buraya girin

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()

@b.add_function()
def kederrack_unpacking(l):
    return [f for f, *_ in l]


@b.add_function()
def rakesh_by_index(l):
    return [i[0] for i in l]


@b.add_function()
def wayneSan_zip(l):
    return list(list(zip(*l))[0])


@b.add_function()
def bcattle_itemgetter(l):
     return list(map(operator.itemgetter(0), l))


@b.add_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [tuple(random.choice(range(100)) for _
                     in range(random.choice(range(2, 100)))) for _ in range(size)]

from pylab import rcParams
rcParams['figure.figsize'] = 12, 7

r = b.run()
r.plot()

0

Bunlar tuples, set değil. Bunu yapabilirsiniz:

l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(1,), (2,)]

2
Gerçekten ne soruluyor
Mad Physicist

0

Eğer yapabilirsiniz açmak için dizilerini ve bir liste anlama kullanarak sadece ilk elemanı almak:

l = [(1, u'abc'), (2, u'def')]
[f for f, *_ in l]

çıktı:

[1, 2]

bir demet içinde ne kadar elemanınız olursa olsun, bu işe yarayacaktır:

l = [(1, u'abc'), (2, u'def', 2, 4, 5, 6, 7)]
[f for f, *_ in l]

çıktı:

[1, 2]

0

Neden kimsenin numpy kullanmayı önermediğini merak ettim, ama şimdi kontrol ettikten sonra anlıyorum. Karışık tip diziler için belki de en iyisi değildir.

Bu numpy'de bir çözüm olurdu:

>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.