Tạo một từ điển với danh sách hiểu


1280

Tôi thích cú pháp hiểu danh sách Python.

Nó có thể được sử dụng để tạo từ điển quá không? Ví dụ: bằng cách lặp qua các cặp khóa và giá trị:

mydict = {(k,v) for (k,v) in blah blah blah}  # doesn't work

Liên quan: collections.Counterlà một loại dict chuyên dùng để đếm các thứ: Sử dụng từ điển để đếm các mục trong danh sách
smci

Câu trả lời:


1898

Từ Python 2.7 và 3 trở đi, bạn chỉ nên sử dụng cú pháp hiểu chính tả :

{key: value for (key, value) in iterable}

Trong Python 2.6 trở về trước, tích dicthợp sẵn có thể nhận được một cặp khóa / giá trị lặp lại, do đó bạn có thể truyền cho nó một sự hiểu biết danh sách hoặc biểu thức trình tạo. Ví dụ:

dict((key, func(key)) for key in keys)

Tuy nhiên, nếu bạn đã có (các) khóa và / hoặc vals lặp lại, bạn hoàn toàn không cần sử dụng một cách hiểu - đơn giản nhất là chỉ cần gọi dicttrực tiếp tích hợp:

# consumed from any iterable yielding pairs of keys/vals
dict(pairs)

# "zipped" from two separate iterables of keys/vals
dict(zip(list_of_keys, list_of_values))

1
Điều gì xảy ra nếu tôi có một trường hợp danh sách các từ ['cat', 'dog', 'cat'] và tôi muốn tạo ra một lệnh với khóa là từ và giá trị như đếm? Có một cú pháp hiệu quả ngắn cho điều đó?
cryanbhu

@cryanbhu nếu những gì bạn có nghĩa là để đếm số lần lặp lại của một nguyên tố trong danh sách, có một lớp Counter trong gói bộ sưu tập: docs.python.org/2/library/collections.html#collections.Counter
fortran


57

Trong thực tế, bạn thậm chí không cần phải lặp đi lặp lại nếu nó đã hiểu một số loại ánh xạ, hàm tạo chính tả thực hiện nó một cách ân cần cho bạn:

>>> ts = [(1, 2), (3, 4), (5, 6)]
>>> dict(ts)
{1: 2, 3: 4, 5: 6}
>>> gen = ((i, i+1) for i in range(1, 6, 2))
>>> gen
<generator object <genexpr> at 0xb7201c5c>
>>> dict(gen)
{1: 2, 3: 4, 5: 6}

40

Trong Python 2.7, nó giống như:

>>> list1, list2 = ['a', 'b', 'c'], [1,2,3]
>>> dict( zip( list1, list2))
{'a': 1, 'c': 3, 'b': 2}

Zip chúng !


11
Điều này không giải quyết câu hỏi nào cả.
Jean-François Corbett

32

Tạo một từ điển với danh sách hiểu trong Python

Tôi thích cú pháp hiểu danh sách Python.

Nó có thể được sử dụng để tạo từ điển quá không? Ví dụ: bằng cách lặp qua các cặp khóa và giá trị:

mydict = {(k,v) for (k,v) in blah blah blah}

Bạn đang tìm kiếm cụm từ "hiểu chính tả" - thực ra là:

mydict = {k: v for k, v in iterable}

Giả sử blah blah blahlà một lặp đi lặp lại của hai tuple - bạn rất gần gũi. Hãy tạo ra một số "blahs" như thế:

blahs = [('blah0', 'blah'), ('blah1', 'blah'), ('blah2', 'blah'), ('blah3', 'blah')]

Cú pháp hiểu Dict:

Bây giờ cú pháp ở đây là phần ánh xạ. Điều làm cho điều này trở thành một sự dicthiểu biết thay vì một sự sethiểu biết (đó là những gì mã giả của bạn gần đúng) là dấu hai chấm, :như dưới đây:

mydict = {k: v for k, v in blahs}

Và chúng tôi thấy rằng nó đã hoạt động và nên giữ nguyên thứ tự chèn như của Python 3.7:

>>> mydict
{'blah0': 'blah', 'blah1': 'blah', 'blah2': 'blah', 'blah3': 'blah'}

Trong Python 2 và lên tới 3.6, thứ tự không được đảm bảo:

>>> mydict
{'blah0': 'blah', 'blah1': 'blah', 'blah3': 'blah', 'blah2': 'blah'}

Thêm bộ lọc:

Tất cả các tính năng hiểu đều có thành phần ánh xạ và thành phần lọc mà bạn có thể cung cấp với các biểu thức tùy ý.

Vì vậy, bạn có thể thêm một phần bộ lọc vào cuối:

>>> mydict = {k: v for k, v in blahs if not int(k[-1]) % 2}
>>> mydict
{'blah0': 'blah', 'blah2': 'blah'}

Ở đây chúng tôi chỉ kiểm tra xem ký tự cuối cùng chia hết cho 2 để lọc dữ liệu trước khi ánh xạ các khóa và giá trị.


23

Phiên bản Python <2.7 (RIP, ngày 3 tháng 7 năm 2010 - 31 tháng 12 năm 2019) , thực hiện như sau:

d = dict((i,True) for i in [1,2,3])

Phiên bản Python> = 2.7, làm như sau:

d = {i: True for i in [1,2,3]}

22

Để thêm vào câu trả lời của @ fortran, nếu bạn muốn lặp lại danh sách các khóa key_listcũng như danh sách các giá trị value_list:

d = dict((key, value) for (key, value) in zip(key_list, value_list))

hoặc là

d = {(key, value) for (key, value) in zip(key_list, value_list)}

6

Đây là một ví dụ khác về việc tạo từ điển bằng cách hiểu dict:

Những gì tôi đang cố gắng làm ở đây là tạo ra một từ điển bảng chữ cái trong đó mỗi cặp; là chữ cái tiếng Anh và vị trí tương ứng của nó trong bảng chữ cái tiếng Anh

>>> import string
>>> dict1 = {value: (int(key) + 1) for key, value in 
enumerate(list(string.ascii_lowercase))}
>>> dict1
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'g': 7, 'f': 6, 'i': 9, 'h': 8, 
'k': 11, 'j': 10, 'm': 13, 'l': 12, 'o': 15, 'n': 14, 'q': 17, 'p': 16, 's': 
19, 'r': 18, 'u': 21, 't': 20, 'w': 23, 'v': 22, 'y': 25, 'x': 24, 'z': 26}
>>> 

Lưu ý việc sử dụng phép liệt kê ở đây để lấy danh sách bảng chữ cái và chỉ mục của chúng trong danh sách và hoán đổi bảng chữ cái và chỉ mục để tạo cặp giá trị khóa cho từ điển

Hy vọng nó mang lại một ý tưởng tốt về từ điển comp cho bạn và khuyến khích bạn sử dụng nó thường xuyên hơn để làm cho mã của bạn nhỏ gọn


1
Câu trả lời hay - đơn giản hóa:d = {k: v+1 for v, k in enumerate(string.ascii_lowercase)}
johnnydrama 6/2/18

4

Thử cái này,

def get_dic_from_two_lists(keys, values):
    return { keys[i] : values[i] for i in range(len(keys)) }

Giả sử chúng ta có hai danh sách quốc giathủ đô

country = ['India', 'Pakistan', 'China']
capital = ['New Delhi', 'Islamabad', 'Beijing']

Sau đó tạo từ điển từ hai danh sách:

print get_dic_from_two_lists(country, capital)

Đầu ra là như thế này,

{'Pakistan': 'Islamabad', 'China': 'Beijing', 'India': 'New Delhi'}

9
bạn có thể đã sử dụng zip
Andre Simon

2
>>> {k: v**3 for (k, v) in zip(string.ascii_lowercase, range(26))}

Python hỗ trợ khả năng hiểu chính tả, cho phép bạn thể hiện việc tạo từ điển trong thời gian chạy bằng cách sử dụng cú pháp ngắn gọn tương tự.

Việc hiểu từ điển có dạng {key: value cho (key, value) trong iterable}. Cú pháp này được giới thiệu trong Python 3 và được nhập vào như Python 2.7, vì vậy bạn sẽ có thể sử dụng nó bất kể phiên bản Python nào bạn đã cài đặt.

Một ví dụ điển hình là lấy hai danh sách và tạo một từ điển trong đó mục ở mỗi vị trí trong danh sách đầu tiên trở thành khóa và mục ở vị trí tương ứng trong danh sách thứ hai trở thành giá trị.

Hàm zip được sử dụng bên trong sự hiểu biết này trả về một bộ lặp của bộ dữ liệu, trong đó mỗi phần tử trong bộ dữ liệu được lấy từ cùng một vị trí trong mỗi lần lặp đầu vào. Trong ví dụ trên, trình lặp được trả về có chứa các bộ dữ liệu (Lv a, 1), (Phong biêu, 2), v.v.

Đầu ra:

{'i': 512, 'e': 64, 'o': 2744, 'h': 343, 'l': 1331, 's': 5832, 'b': 1, 'w': 10648, ' c ': 8,' x ': 12167,' y ': 13824,' t ': 6859,' p ': 3375,' d ': 27,' j ': 729,' a ': 0' ' : 15625, 'f': 125, 'q': 4096, 'u': 8000, 'n': 2197, 'm': 1728, 'r': 4913, 'k': 1000, 'g': 216 , 'v': 9261}


2

Mã này sẽ tạo từ điển bằng cách hiểu danh sách cho nhiều danh sách với các giá trị khác nhau có thể được sử dụng cho pd.DataFrame()

#Multiple lists 
model=['A', 'B', 'C', 'D']
launched=[1983,1984,1984,1984]
discontinued=[1986, 1985, 1984, 1986]

#Dictionary with list comprehension
keys=['model','launched','discontinued']
vals=[model, launched,discontinued]
data = {key:vals[n] for n, key in enumerate(keys)}

enumeratesẽ vượt qua nđể valskhớp với từng keydanh sách


1

Chỉ để ném vào một ví dụ khác. Hãy tưởng tượng bạn có danh sách sau đây:

nums = [4,2,2,1,3]

và bạn muốn biến nó thành một dict trong đó khóa là chỉ mục và giá trị là thành phần trong danh sách. Bạn có thể làm như vậy với dòng mã sau:

{index:nums[index] for index in range(0,len(nums))}

0

Bạn có thể tạo một dict mới cho mỗi cặp và hợp nhất nó với dict trước:

reduce(lambda p, q: {**p, **{q[0]: q[1]}}, bla bla bla, {})

Rõ ràng phương pháp này đòi hỏi reducetừ functools.


cùng một ý tưởng: giảm (lambda p, q: {** p, ** dict ([q])}, bla bla bla, {})
Mahmoud Khaled
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.