2013-01-24 105 views
289

Có thể tạo một từ điển hiểu bằng Python (cho các phím) không?Tra cứu từ điển Python

Without comprehensions danh sách, bạn có thể sử dụng một cái gì đó như thế này:

l = [] 
for n in range(1, 11): 
    l.append(n) 

Chúng ta có thể rút ngắn này cho một người hiểu danh sách: l = [n for n in range(1, 11)].

Tuy nhiên, giả sử tôi muốn đặt khóa của từ điển có cùng giá trị. tôi có thể làm:

d = {} 
for n in range(1, 11): 
    d[n] = True # same value for each 

Tôi đã thử điều này:

d = {} 
d[i for i in range(1, 11)] = True 

Tuy nhiên, tôi nhận được một SyntaxError trên for.

Bên cạnh đó (tôi không cần phần này, nhưng chỉ cần tự hỏi), bạn có thể thiết lập phím của một từ điển để một loạt các giá trị khác nhau, như thế này:

d = {} 
for n in range(1, 11): 
    d[n] = n 

Đây có phải là có thể với một sự hiểu biết từ điển ?

d = {} 
d[i for i in range(1, 11)] = [x for x in range(1, 11)] 

Điều này cũng tăng SyntaxError trên for.

+1

Để biết thông tin của người đọc trong tương lai: mảng NumPy cho phép bạn đặt nhiều phần tử thành một giá trị hoặc danh sách giá trị, cách bạn đang cố gắng thực hiện. Mặc dù nếu bạn chưa có lý do để sử dụng NumPy, có thể nó không đáng để chỉ sử dụng tính năng này. –

Trả lời

390

dictionary comprehensions in Python 2.7+, nhưng chúng không hoạt động theo cách bạn đang cố gắng. Giống như việc hiểu danh sách, họ tạo một từ điển mới mới; bạn không thể sử dụng chúng để thêm khóa vào một từ điển hiện có. Ngoài ra, bạn phải chỉ định khóa và giá trị, mặc dù tất nhiên bạn có thể chỉ định giá trị giả nếu bạn muốn.

>>> d = {n: n**2 for n in range(5)} 
>>> print d 
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 

Nếu bạn muốn thiết lập tất cả chúng là True:

>>> d = {n: True for n in range(5)} 
>>> print d 
{0: True, 1: True, 2: True, 3: True, 4: True} 

gì bạn dường như được yêu cầu là một cách để đặt nhiều phím cùng một lúc trên một cuốn từ điển hiện có. Không có lối tắt trực tiếp nào cho điều đó. Bạn có thể lặp lại như bạn đã cho thấy, hoặc bạn có thể sử dụng một từ điển hiểu để tạo ra một dict mới với các giá trị mới, và sau đó làm oldDict.update(newDict) để hợp nhất các giá trị mới vào dict cũ.

+10

FWIW, 'dict.update' cũng có thể chấp nhận các cặp khóa-giá trị lặp lại giống như hàm tạo' dict' – mgilson

+1

Lưu ý rằng nếu bạn tạo một từ điển có tất cả các giá trị giống nhau, hãy sử dụng 'dict.fromkeys()'. Vì vậy, để thiết lập tất cả các giá trị thành 'True', sử dụng' dict.fromkeys (range (5), True) '. Xem ra, giá trị là * không được sao chép *, vì vậy bạn có thể muốn tránh điều này khi bạn có một giá trị có thể thay đổi được; nó sẽ được chia sẻ giữa tất cả các phím. –

+1

Lưu ý: các khóa cũng có thể là kết quả của một phương thức: '{n * 2: n cho n trong phạm vi (3)} => {0: 0, 2: 1, 4: 2}'. Cả hai có thể được thực hiện trong cùng một biểu thức: '{n * 2: n * 3 cho n trong phạm vi (3)} => {0: 0, 2: 3, 4: 6}'. – Zaaier

136

Bạn có thể sử dụng phương pháp dict.fromkeys lớp ...

>>> dict.fromkeys(range(1, 11), True) 
{1: True, 2: True, 3: True, 4: True, 5: True, 6: True, 7: True, 8: True, 9: True, 10: True} 

Đây là cách nhanh nhất để tạo ra một từ điển, nơi bản đồ tất cả các phím để cùng giá trị.

Hãy cẩn thận sử dụng này với các đối tượng có thể thay đổi mặc dù:

d = dict.fromkeys(range(10), []) 
d[1].append(2) 
print(d[2]) # ??? 

Nếu bạn không thực sự cần để khởi tạo tất cả các phím, một defaultdict có thể có ích cũng như:

from collections import defaultdict 
d = defaultdict(lambda: True) 

Để trả lời phần thứ hai, việc hiểu dict chỉ là những gì bạn cần:

{k: k for k in range(10)} 

Hoặc cho python2.6:

dict((k, k) for k in range(10)) 

Bạn cũng có thể tạo ra một lớp con thông minh của dict mà tác động giống như một defaultdict nếu bạn ghi đè __missing__:

>>> class KeyDict(dict): 
... def __missing__(self, key): 
...  #self[key] = key # Maybe add this also??? 
...  return key 
... 
>>> d = KeyDict() 
>>> d[1] 
1 
>>> d[2] 
2 
>>> d[3] 
3 
>>> print(d) 
{} 

gọn gàng.

+0

Lưu ý rằng trong trường hợp 'd = defaultdict (lambda: True)', lambda không được yêu cầu là True (hoặc không nên) có thể thay đổi được. – rhbvkleef

21
>>> {i:i for i in range(1, 11)} 
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10} 
10

Sử dụng dict() trên một danh sách các hàng, giải pháp này sẽ cho phép bạn có giá trị tùy ý trong mỗi danh sách, vì vậy miễn là họ có cùng độ dài

i_s = range(1, 11) 
x_s = range(1, 11) 
# x_s = range(11, 1, -1) # Also works 
d = dict([(i_s[index], x_s[index],) for index in range(len(i_s))]) 
+10

Là một lưu ý phụ, điều này giống với 'd = dict (zip (i_s, x_s))' – mgilson

-2

bạn không thể băm một danh sách như thế. thử này thay vào đó, nó sử dụng các bộ

d[tuple([i for i in range(1,11)])] = True 
+6

Điều này không làm gì cả với những gì OP muốn ... –

6

Mục đích chính của một sự hiểu biết danh sách là tạo ra một danh sách mới dựa vào nhau mà không thay đổi hoặc phá hủy danh sách ban đầu.

Thay vì viết

l = [] 
    for n in range(1, 11): 
     l.append(n) 

hoặc

l = [n for n in range(1, 11)] 

bạn nên viết chỉ

l = range(1, 11) 

Trong hai khối mã đầu bạn đang tạo một danh sách mới, iterating qua nó và chỉ trả về từng phần tử. Nó chỉ là một cách đắt tiền để tạo ra một bản sao danh sách.

Để có được một cuốn từ điển mới với tất cả các phím thiết lập để cùng giá trị dựa trên dict khác, làm điều này:

old_dict = {'a': 1, 'c': 3, 'b': 2} 
    new_dict = { key:'your value here' for key in old_dict.keys()} 

Bạn nhận được một Lỗi Cú pháp bởi vì khi bạn viết

d = {} 
    d[i for i in range(1, 11)] = True 

bạn về cơ bản nói: "Đặt khóa của tôi 'i cho i trong phạm vi (1, 11)' thành True" và "i for i in range (1, 11)" không phải là khóa hợp lệ, đó chỉ là lỗi cú pháp. Nếu dicts hỗ trợ danh sách như phím, bạn sẽ làm cái gì đó như

d[[i for i in range(1, 11)]] = True 

và không

d[i for i in range(1, 11)] = True 

nhưng danh sách không hashable, vì vậy bạn không thể sử dụng chúng như phím dict.

16

Tôi thực sự thích nhận xét @mgilson, vì nếu bạn có hai lần lặp lại, cái tương ứng với khóa và giá trị khác, bạn cũng có thể làm như sau.

keys = ['a', 'b', 'c'] 
values = [1, 2, 3] 
d = dict(zip(keys, values)) 

cho

d = { 'a': 1, 'b': 2, 'c': 3}

9

Hãy xem xét ví dụ này đếm sự xuất hiện của từ trong một danh sách sử dụng từ điển hiểu

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello'] 
my_dict = {k:my_list.count(k) for k in my_list} 
print(my_dict) 

Và kết quả là

01.
{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1} 
+0

Điều này thật thú vị, mặc dù không hiệu quả nhất khi bạn sẽ đếm các phím như 'hello' nhiều lần – FuriousGeorge

Các vấn đề liên quan