Làm thế nào để có được phần tử đầu tiên trong một danh sách các bộ dữ liệu?


178

Tôi có một danh sách như bên dưới trong đó phần tử đầu tiên là id và phần còn lại là một chuỗi:

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

Tôi muốn tạo một danh sách id chỉ từ danh sách các bộ dữ liệu này như sau:

[1,2]

Tôi sẽ sử dụng danh sách này __inđể nó cần phải là danh sách các giá trị nguyên.

Câu trả lời:


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

68

Sử dụng chức năng zip để tách các phần tử:

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

Chỉnh sửa (@BradSolomon): Phần trên hoạt động với Python 2.x, trong đó ziptrả về một danh sách.

Trong Python 3.x, ziptrả về một trình vòng lặp và các điều sau đây tương đương với ở trên:

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

cái này có cần nhập riêng không?
JuliandotNut

2
@JuliandotNut Không, đó là một chức năng tích hợp. (trong Python 2.x)
WayneSan

22

bạn có ý gì như thế này?

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

Những gì bạn thực sự có là một danh sách các tupleđối tượng, không phải là một danh sách các bộ (như câu hỏi ban đầu của bạn ngụ ý). Nếu nó thực sự là một danh sách các tập hợp, thì không có phần tử đầu tiên vì các tập hợp không có thứ tự.

Ở đây tôi đã tạo một danh sách phẳng vì nhìn chung điều đó có vẻ hữu ích hơn so với việc tạo danh sách 1 bộ dữ liệu phần tử. Tuy nhiên, bạn có thể dễ dàng tạo danh sách 1 bộ dữ liệu bằng cách thay thế seq[0]bằng (seq[0],).


Tôi đã thử nó. Nó đưa ra lỗi này:int() argument must be a string or a number, not 'QuerySet'
wasimbhalli

4
@wasimbhalli - int()không có trong giải pháp của tôi, vì vậy ngoại lệ bạn thấy phải xuất hiện sau trong mã.
mgilson

Tôi đã cập nhật câu hỏi, tôi cần sử dụng danh sách này sau __inđể lọc dữ liệu
wasimbhalli

__ingì - Dựa trên ví dụ đầu vào bạn đã đưa ra, điều này sẽ tạo ra một danh sách các số nguyên. Tuy nhiên, nếu danh sách các bộ dữ liệu của bạn không bắt đầu bằng số nguyên, thì bạn sẽ không nhận được số nguyên và bạn sẽ cần tạo số nguyên qua inthoặc thử tìm hiểu tại sao phần tử đầu tiên của bạn không thể được chuyển đổi thành số nguyên.
mgilson

new_list = [ seq[0] for seq in yourlist if type(seq[0]) == int]hoạt động không?
pR0P

11

Bạn có thể sử dụng "bộ giải nén":

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

Tại thời gian lặp, mỗi bộ dữ liệu được giải nén và các giá trị của nó được đặt thành các biến idxval.

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

8

Đây là những gì operator.itemgetterdành cho.

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

Câu itemgetterlệnh trả về một hàm trả về chỉ mục của phần tử bạn chỉ định. Nó giống hệt như viết

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

Nhưng tôi thấy đó itemgetterlà một rõ ràng hơn và rõ ràng hơn .

Điều này rất hữu ích để thực hiện các báo cáo sắp xếp nhỏ gọn. Ví dụ,

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

7

Từ quan điểm hiệu suất, trong python3.X

  • [i[0] for i in a]list(zip(*a))[0]tương đương
  • chúng nhanh hơn list(map(operator.itemgetter(0), a))

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)

đầu ra

3.491014136001468e-05

3,422205176000717e-05


6

Nếu các bộ dữ liệu là duy nhất thì nó có thể hoạt động

>>> 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
Điều này sẽ mất thứ tự. Nó có thể làm việc với ordereddict, mặc dù.
Tim Tonomall

nếu 2 hoặc nhiều bộ dữ liệu có cùng phần tử đầu tiên so với giải pháp của bạn sẽ không hoạt động
kederrac

3

khi tôi chạy (như đề xuất ở trên):

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

thay vì trở về:

[1, 2]

Tôi nhận được điều này khi trở về:

<map at 0xb387eb8>

Tôi thấy tôi phải sử dụng list ():

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

để trả về thành công một danh sách bằng cách sử dụng đề xuất này. Điều đó nói rằng, tôi hài lòng với giải pháp này, cảm ơn. (đã thử nghiệm / chạy bằng Spyder, bảng điều khiển iPython, Python v3.6)


3

Tôi đã nghĩ rằng có thể hữu ích khi so sánh thời gian chạy của các cách tiếp cận khác nhau nên tôi đã tạo một điểm chuẩn (sử dụng Simple_benchmark thư viện )

I) Điểm chuẩn có bộ dữ liệu với 2 yếu tố nhập mô tả hình ảnh ở đây

Như bạn có thể mong đợi để chọn phần tử đầu tiên từ bộ dữ liệu theo chỉ mục 0cho thấy đây là giải pháp nhanh nhất rất gần với giải pháp giải nén bằng cách mong đợi chính xác 2 giá trị

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) Điểm chuẩn có bộ dữ liệu có 2 phần tử trở lên nhập mô tả hình ảnh ở đây

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

Đó là những bộ, không phải bộ. Bạn có thể làm được việc này:

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

2
Không thực sự những gì đang được hỏi
Nhà vật lý điên

0

bạn có thể giải nén bộ dữ liệu của mình và chỉ nhận phần tử đầu tiên bằng cách hiểu danh sách:

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

đầu ra:

[1, 2]

điều này sẽ hoạt động cho dù bạn có bao nhiêu yếu tố trong một tuple:

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

đầu ra:

[1, 2]

0

Tôi tự hỏi tại sao không ai đề nghị sử dụng numpy, nhưng bây giờ sau khi kiểm tra tôi hiểu. Nó có thể không phải là tốt nhất cho mảng hỗn hợp.

Đây sẽ là một giải pháp trong numpy:

>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.