Python ra lệnh làm thế nào để tạo khóa hoặc nối một phần tử vào khóa?


161

Tôi có một từ điển trống. Tên: dict_x Nó có các khóa trong đó các giá trị là danh sách.

Từ một lần lặp riêng biệt, tôi có được một khóa (ví dụ key_123:) và một mục (một tuple) để đặt trong danh sách dict_xgiá trị key_123.

Nếu khóa này đã tồn tại, tôi muốn nối thêm mục này. Nếu khóa này không tồn tại, tôi muốn tạo nó với một danh sách trống và sau đó thêm vào nó hoặc chỉ tạo nó với một tuple trong đó.

Trong tương lai khi một lần nữa khóa này xuất hiện, vì nó tồn tại, tôi muốn giá trị được nối lại.

Mã của tôi bao gồm:

Nhận chìa khóa và giá trị.

Xem nếu khóa KHÔNG tồn tại trong dict_x.

và nếu không tạo ra nó: dict_x[key] == []

Sau đó: dict_x[key].append(value)

Đây có phải là cách để làm điều đó? Tôi sẽ thử sử dụng try/exceptcác khối?

Câu trả lời:


253

Sử dụng dict.setdefault():

dic.setdefault(key,[]).append(value)

trợ giúp (dict.setdefault) :

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

4
Tôi đã từng làm điều này bằng cách dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]nhưng câu trả lời này cho thấy một cách tốt hơn nhiều. Trong thực tế, nó set()là một đối số và cho phép bạn sử dụng add()phương thức ...
fatih_dur 9/2/2016

66

Dưới đây là những cách khác nhau để làm điều này để bạn có thể so sánh nó trông như thế nào và chọn những gì bạn thích. Tôi đã ra lệnh cho họ theo cách mà tôi nghĩ là "pythonic" nhất , và nhận xét những ưu và nhược điểm có thể không rõ ràng ngay từ cái nhìn đầu tiên:

Sử dụng collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Ưu điểm: Có lẽ là hiệu suất tốt nhất. Nhược điểm: Không có sẵn trong Python 2.4.x.

Sử dụng dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Nhược điểm: Tạo không hiệu quả của list()s không sử dụng .

Sử dụng try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

Hoặc là:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]

Xin chào, tại sao bạn nghĩ .setdefault tạo ra các từ điển không cần thiết?
Phil

2
Tôi không nghĩ .setdefault()tạo ra từ điển không cần thiết. Tôi nghĩ rằng tôi đang tạo list(các []) không cần thiết trong đối số thứ hai .setdefault()không bao giờ được sử dụng nếu keyđã tồn tại. Tôi có thể sử dụng dict.setdefault()(vì lợi ích của việc băm khóa hiệu quả) và sử dụng một biến để sử dụng lại listcác s không được sử dụng nhưng điều đó thêm một vài dòng mã.
antak

1
IIRC, trong Python, một danh sách trống trong một đẳng thức được coi là hằng số ở cấp mã byte, nhưng điều này cần một số xác nhận của một guru mã byte (hoặc chỉ sử dụng mô-đun disas).
gabious

Việc sử dụng .setdefaultsẽ tạo ra việc dicttìm kiếm khóa vắng mặt thường xuyên trong một KeyErrorthời gian collections.defaultdict(list)sẽ tạo ra một dictnơi mà việc tra cứu khóa vắng mặt sẽ chèn trống list- tôi nghĩ bạn nên chọn dựa trên hành vi nào bạn muốn
Chris_Rands

Tôi đã thử một cái gì đó tương tự như bộ sưu tập.defaultdict trong mã của riêng tôi và nó có tác dụng phụ không mong muốn. Ví dụ, hãy xem xét trao đổi IDLE sau: >>> list_dict = defaultdict (list) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Nó xuất hiện khi Python gọi giá trị mặc định nó thêm khóa vào từ điển mà không cần bạn chủ động cài đặt nó, điều này sẽ tạo ra rất nhiều danh sách trống nếu mặc định được sử dụng nhiều. Tôi sẽ cuộn các hàm bao bọc của riêng mình cho từ điển, không hiệu quả nhưng hy vọng sẽ dễ đoán hơn.
RDBury

26

Bạn có thể sử dụng một defaultdict cho việc này.

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

Điều này hiệu quả hơn một chút so với setdefaultkhi bạn không tạo danh sách mới mà cuối cùng bạn không sử dụng. Mỗi cuộc gọi đến setdefaultsẽ tạo một danh sách mới, ngay cả khi mục đó đã tồn tại trong từ điển.


14

Bạn có thể sử dụng defaultdict trong collections.

Một ví dụ từ doc:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)

0
dictionary['key'] = dictionary.get('key', []) + list_to_append

1
Bạn nên giải thích lợi thế (rất nhỏ) mà điều này có trong trường hợp ngoại lệ nhất định; chỉ là mã, không rõ tại sao cần câu trả lời bổ sung.
Davis Herring

Xin chào, chỉ là một thay thế mà không cần nhập thêm. Điều này rõ ràng có thể được thực hiện với một câu lệnh if. Tôi chỉ đề xuất một giải pháp thay thế bằng cách sử dụng sức mạnh của .get () thay vì sử dụng dict [].
Tomas Silva Ebensperger

Hai câu trả lời hàng đầu đề cập đến hai cách khác nhau mà không nhập khẩu (mặc dù không dict.get).
Davis Herring
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.