Làm thế nào tôi có thể sử dụng if / other trong việc hiểu từ điển?


138

Có tồn tại một cách trong Python 2.7+ để tạo ra một cái gì đó như sau không?

{ something_if_true if condition else something_if_false for key, value in dict_.items() }

Tôi biết bạn có thể làm bất cứ điều gì chỉ với 'nếu':

{ something_if_true for key, value in dict_.items() if condition}

4
như được nói bởi @Marcin, a dictđược tạo thành từ key:valuecác yếu tố, bạn không xây dựng dictở đây mà là một set(xem tập hợp chữ ).
vui vẻ

Câu trả lời:


246

Bạn đã có nó: A if test else Blà một biểu thức Python hợp lệ. Vấn đề duy nhất với cách hiểu chính tả của bạn như được hiển thị là vị trí cho một biểu thức trong cách hiểu chính tả phải có hai biểu thức, cách nhau bằng dấu hai chấm:

{ (some_key if condition else default_key):(something_if_true if condition
          else something_if_false) for key, value in dict_.items() }

ifMệnh đề cuối cùng hoạt động như một bộ lọc, khác với việc có biểu thức điều kiện.


28
Đáng nói là bạn không cần phải có điều kiện if-other cho cả khóa và giá trị. Ví dụ, {(a if condition else b): value for key, value in dict.items()}sẽ làm việc.
Jeremy Weirich

5
@Jeremy Weirich Bạn không cần phải có if-if cho một trong số họ nếu bạn không muốn.
Marcin

@Marcin Tôi có thể chỉ sử dụng "if" cho phần chính và sử dụng cả "if" và "other" cho phần giá trị không?
nithin11

14

Câu trả lời của @ Marcin bao gồm tất cả, nhưng chỉ trong trường hợp ai đó muốn xem một ví dụ thực tế, tôi thêm hai câu dưới đây:

Giả sử bạn có bộ từ điển sau đây của bộ

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

và bạn muốn tạo một từ điển mới có các khóa cho biết chuỗi 'a'có được chứa trong các giá trị hay không, bạn có thể sử dụng

dout = {"a_in_values_of_{}".format(k) if 'a' in v else "a_not_in_values_of_{}".format(k): v for k, v in d.items()}

mang lại

{'a_in_values_of_key1': {'a', 'b', 'c'},
 'a_not_in_values_of_key2': {'bar', 'foo'},
 'a_not_in_values_of_key3': {'sad', 'so'}}

Bây giờ hãy giả sử bạn có hai từ điển như thế này

d1 = {'bad_key1': {'a', 'b', 'c'}, 'bad_key2': {'foo', 'bar'}, 'bad_key3': {'so', 'sad'}}
d2 = {'good_key1': {'foo', 'bar', 'xyz'}, 'good_key2': {'a', 'b', 'c'}}

và bạn muốn thay thế các khóa d1bằng các khóa d2nếu có các giá trị tương ứng giống hệt nhau, bạn có thể làm

# here we assume that the values in d2 are unique
# Python 2
dout2 = {d2.keys()[d2.values().index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

# Python 3
dout2 = {list(d2.keys())[list(d2.values()).index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

cái nào cho

{'bad_key2': {'bar', 'foo'},
 'bad_key3': {'sad', 'so'},
 'good_key2': {'a', 'b', 'c'}}

cho ví dụ thứ hai của bạn bằng cách sử dụng d1, d2tôi nhận đượcAttributeError: 'dict_values' object has no attribute 'index'
alancalvitti

@alancalvitti: cảm ơn vì đã chỉ ra điều này! Giải pháp là cho Python 2 và không hoạt động cho Python 3; Tôi cũng đã thêm một giải pháp Python 3.
Khóa

3

Trong trường hợp bạn có các điều kiện khác nhau để đánh giá các khóa và giá trị, câu trả lời của @ Marcin là cách để đi.

Nếu bạn có cùng điều kiện cho các khóa và giá trị, tốt hơn hết là bạn nên xây dựng (khóa, giá trị) -tuples trong biểu thức trình tạo cho vào dict():

dict((modify_k(k), modify_v(v)) if condition else (k, v) for k, v in dct.items())

Nó dễ đọc hơn và điều kiện chỉ được đánh giá một lần cho mỗi khóa, giá trị.

Ví dụ với việc mượn từ điển của bộ @ Cleb:

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

Giả sử bạn chỉ muốn có hậu tố keysvới avaluevà bạn muốn valuethay thế bằng độ dài của tập hợp trong trường hợp đó. Mặt khác, cặp khóa-giá trị sẽ không thay đổi.

dict((f"{k}_a", len(v)) if "a" in v else (k, v) for k, v in d.items())
# {'key1_a': 3, 'key2': {'bar', 'foo'}, 'key3': {'sad', 'so'}}

0

Một ví dụ khác trong việc sử dụng if / other trong hiểu từ điển

Tôi đang làm việc trên ứng dụng máy tính để nhập dữ liệu cho công việc văn phòng của riêng tôi và thông thường ứng dụng nhập dữ liệu đó sẽ lấy tất cả các mục từ tiện ích nhập liệu và chuyển nó vào từ điển để xử lý thêm như xác thực hoặc chỉnh sửa mà chúng tôi phải trả lại dữ liệu được chọn từ tệp trở lại các mục nhập, v.v.

Vòng đầu tiên sử dụng mã hóa truyền thống (8 dòng):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic, b_dic = {}, {}

for field, value in entries.items():
    if field == 'ther':
        for k,v in value.items():
            b_dic[k] = v
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Vòng thứ hai tôi đã cố gắng sử dụng khả năng hiểu từ điển nhưng vòng lặp vẫn còn đó (6 dòng):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

for field, value in entries.items():
    if field == 'ther':
        b_dic = {k:v for k,v in value.items()}
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Cuối cùng, với câu lệnh hiểu từ điển một dòng (1 dòng):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic = {field:{k:v for k,v in value.items()} if field == 'ther' 
        else value for field, value in entries.items()}
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Tôi sử dụng trăn 3.8.3

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.