Chuyển đổi danh sách thành từ điển trong Python


189

Giả sử tôi có một danh sách atrong Python có các mục được ánh xạ thuận tiện vào từ điển. Mỗi phần tử chẵn đại diện cho khóa cho từ điển và phần tử lẻ sau đây là giá trị

ví dụ,

a = ['hello','world','1','2']

và tôi muốn chuyển nó sang một cuốn từ điển b, nơi

b['hello'] = 'world'
b['1'] = '2'

Cách tổng hợp sạch nhất để thực hiện điều này là gì?


3
Bản sao có thể có của Make dictionary từ danh sách với python
Jeru Luke

Câu trả lời:


269
b = dict(zip(a[::2], a[1::2]))

Nếu alớn, có lẽ bạn sẽ muốn làm một cái gì đó như sau, mà không tạo ra bất kỳ danh sách tạm thời như ở trên.

from itertools import izip
i = iter(a)
b = dict(izip(i, i))

Trong Python 3, bạn cũng có thể sử dụng một cách hiểu chính tả, nhưng trớ trêu thay tôi nghĩ rằng cách đơn giản nhất để làm điều đó sẽ là range()len()thường là mùi mã.

b = {a[i]: a[i+1] for i in range(0, len(a), 2)}

Vì vậy, iter()/izip()phương thức này có lẽ vẫn là Pythonic nhất trong Python 3, mặc dù như EOL ghi chú trong một nhận xét, zip()đã lười biếng trong Python 3 nên bạn không cần izip().

i = iter(a)
b = dict(zip(i, i))

Nếu bạn muốn nó trên một dòng, bạn sẽ phải gian lận và sử dụng dấu chấm phẩy. ;-)


9
Hay đơn giản zip(i, i), trong Python 3, kể từ zip()bây giờ trả về một trình vòng lặp.
Eric O Lebigot

5
Lưu ý rằng Python 2.7.3 cũng có khả năng hiểu chính tả
user1438003

56

Câu trả lời đơn giản

Một lựa chọn khác (lịch sự của Alex Martelli - nguồn ):

dict(x[i:i+2] for i in range(0, len(x), 2))

Lưu ý liên quan

Nếu bạn có điều này:

a = ['bi','double','duo','two']

và bạn muốn điều này (mỗi phần tử của danh sách khóa một giá trị đã cho (2 trong trường hợp này)):

{'bi':2,'double':2,'duo':2,'two':2}

bạn có thể dùng:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}

2
Đây có phải chỉ dành cho Python 3 không?
Tagar

2
sử dụng fromkeys. >>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2}
Gdogg

1
Đây là làm một cái gì đó khác hơn những gì câu hỏi đang hỏi.
ozn

17

Bạn có thể sử dụng một cách hiểu chính tả cho việc này khá dễ dàng:

a = ['hello','world','1','2']

my_dict = {item : a[index+1] for index, item in enumerate(a) if index % 2 == 0}

Điều này tương đương với vòng lặp for bên dưới:

my_dict = {}
for index, item in enumerate(a):
    if index % 2 == 0:
        my_dict[item] = a[index+1]

10

Một cái gì đó tôi thấy khá tuyệt, đó là nếu danh sách của bạn chỉ dài 2 mục:

ls = ['a', 'b']
dict([ls])
>>> {'a':'b'}

Hãy nhớ rằng, dict chấp nhận bất kỳ iterable nào có chứa một iterable trong đó mỗi mục trong iterable phải là một iterable với chính xác hai đối tượng.


một cách nhanh chóng và đơn giản, chỉ cần thêm nếu danh sách chứa nhiều hơn hai mục sau đó sử dụng dict (ls) thay vì dict ([ls]). ví dụ: nếu ls = ['a', 'b', 'c', 'd'] thì dict (ls)
ankit tyagi

1
Đẹp & kiểu dáng đẹp. 'mỗi mục trong iterable phải là một iterable với chính xác hai đối tượng.' là thực tế quan trọng ở đây.
Abhijeet

4

Có thể không phải là pythonic nhất, nhưng

>>> b = {}
>>> for i in range(0, len(a), 2):
        b[a[i]] = a[i+1]

10
đọc vềenumerate
SilentGhost

5
liệt kê không cho phép bạn chỉ định kích thước bước, nhưng bạn có thể sử dụng for i, key in enumerate(a[::2]):. Vẫn còn unpythonic vì nhà xây dựng chính tả có thể thực hiện hầu hết các công việc ở đây cho bạn
John La Rooy

@SilentGhost, gnibbler: cảm ơn rất nhiều vì đã mở rộng tầm nhìn của tôi! Tôi chắc chắn sẽ kết hợp nó nhiều nhất có thể trong tương lai!
sahhhm

@gnibbler: Bạn có thể giải thích thêm một chút về cách for i, key in enumerate(a[::2]):tiếp cận có thể hoạt động không? Các giá trị cặp kết quả sẽ là 0 hello1 1, và tôi không rõ cách sử dụng chúng để sản xuất {'hello':'world', '1':'2'}.
martineau

1
@martineau, bạn đúng rồi. Tôi nghĩ tôi phải có ýenumerate(a)[::2]
John La Rooy

4

Bạn có thể làm điều đó khá nhanh mà không cần tạo thêm mảng, vì vậy điều này sẽ hoạt động ngay cả đối với các mảng rất lớn:

dict(izip(*([iter(a)]*2)))

Nếu bạn có một máy phát điện a, thậm chí còn tốt hơn:

dict(izip(*([a]*2)))

Đây là danh sách:

iter(h)    #create an iterator from the array, no copies here
[]*2       #creates an array with two copies of the same iterator, the trick
izip(*())  #consumes the two iterators creating a tuple
dict()     #puts the tuples into key,value of the dictionary

điều này sẽ tạo một từ điển với các cặp khóa và giá trị bằng nhau ( {'hello':'hello','world':'world','1':'1','2':'2'})
mik

Không, tất cả chỉ hoạt động tốt. Xin vui lòng đọc kỹ hơn. Nó nói: "Nếu bạn có máy phát điện ..." Nếu bạn không có máy phát điện, chỉ cần sử dụng dòng đầu tiên. Cái thứ hai là một sự thay thế sẽ hữu ích nếu bạn có một trình tạo thay vì một danh sách, như hầu hết thời gian.
topkara

1

Bạn cũng có thể làm như thế này (chuỗi để liệt kê chuyển đổi ở đây, sau đó chuyển đổi thành từ điển)

    string_list = """
    Hello World
    Goodbye Night
    Great Day
    Final Sunset
    """.split()

    string_list = dict(zip(string_list[::2],string_list[1::2]))

    print string_list

1

Tôi cũng rất quan tâm để có một lớp lót cho chuyển đổi này, cho đến nay một danh sách như vậy là trình khởi tạo mặc định cho hàm băm trong Perl.

Câu trả lời toàn diện đặc biệt được đưa ra trong chủ đề này -

Của tôi, tôi là người mới sử dụng Python ), sử dụng Biểu thức trình tạo Python 2.7 , sẽ là:

dict((a[i], a[i + 1]) for i in range(0, len(a) - 1, 2))


0

Tôi không chắc đây có phải là pythonic không, nhưng dường như có tác dụng

def alternate_list(a):
   return a[::2], a[1::2]

key_list,value_list = alternate_list(a)
b = dict(zip(key_list,value_list))

0

thử mã dưới đây:

  >>> d2 = dict([('one',1), ('two', 2), ('three', 3)])
  >>> d2
      {'three': 3, 'two': 2, 'one': 1}

0

Bạn cũng có thể thử phương pháp này lưu các khóa và giá trị trong danh sách khác nhau và sau đó sử dụng phương thức dict

data=['test1', '1', 'test2', '2', 'test3', '3', 'test4', '4']

keys=[]
values=[]
for i,j in enumerate(data):
    if i%2==0:
        keys.append(j)
    else:
        values.append(j)

print(dict(zip(keys,values)))

đầu ra:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}

0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

result : {'hello': 'world', '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.