2010-07-21 27 views
8

Tôi có một danh sách các chuỗi phân tích cú pháp từ nơi nào đó, trong các định dạng sau:Cách Pythonic để chuyển danh sách các chuỗi thành từ điển với các chuỗi được lập chỉ mục lẻ làm khóa và các chỉ mục được lập chỉ mục làm giá trị?

[key1, value1, key2, value2, key3, value3, ...] 

tôi muốn tạo một từ điển dựa trên danh sách này, như vậy:

{key1:value1, key2:value2, key3:value3, ...} 

Một bình thường for vòng lặp với chỉ số bù đắp có thể sẽ làm các trick, nhưng tôi tự hỏi nếu có một cách Pythonic làm điều này. Việc hiểu danh sách có vẻ thú vị, nhưng dường như tôi không thể tìm ra cách áp dụng chúng cho vấn đề cụ thể này.

Bất kỳ ý tưởng nào?

Trả lời

13

Bạn có thể thử:

dict(zip(l[::2], l[1::2])) 

Giải thích: chúng tôi chia danh sách thành hai danh sách, một trong những chẵn và một trong những yếu tố kỳ lạ, bằng cách lấy chúng bằng cách bước của hai bắt đầu từ một trong hai người đầu tiên hoặc phần tử thứ hai (đó là số l[::2]l[1::2]). Sau đó, chúng tôi sử dụng nội dung tích hợp zip vào hai danh sách thành một danh sách các cặp. Cuối cùng, chúng tôi gọi dict để tạo từ điển từ các cặp khóa-giá trị này.

Đây là ~4n trong thời gian và ~4n trong không gian, kể cả từ điển cuối cùng. Nó có lẽ là nhanh hơn so với một vòng lặp, tuy nhiên, kể từ khi zip, dict, và các nhà khai thác cắt được viết bằng C.

+0

Chính xác những gì tôi cần và độc đáo giải thích, nhờ một pavpanchekha rất nhiều! – KennyDeriemaeker

0
result = dict(grouper(2, L)) 

grouper là một chức năng mà tạo thành cặp trong một danh sách, nó được đưa ra trong itertools receipes:

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 

dict lấy danh sách (key,value) cặp và đưa ra quyết định từ họ.

Bạn cũng có thể viết result = dict(zip(*[iter(L)]*2)) và nhầm lẫn hầu hết người đọc :-)

+0

'result = dict (zip (* [iter (L)] * 2))' không được bảo đảm hoạt động (zip không đảm bảo về thứ tự đánh giá các đối số của nó). Bạn nên sử dụng 'result = dict (izip (* [iter (L)] * 2))' thay vì ngoài việc là một mô hình rõ ràng (!) Đảm bảo thứ tự đánh giá đúng. – Duncan

+1

@Ducan: Bạn lấy ý tưởng (sai) ở đâu? Xem http://docs.python.org/library/functions.html#zip 'izip' chỉ là phiên bản lặp của' zip'. –

3
In [71]: alist=['key1', 'value1', 'key2', 'value2', 'key3', 'value3'] 

In [72]: dict(alist[i:i+2] for i in range(0,len(alist),2)) 
Out[72]: {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'} 
1

Ngoài giải pháp ngắn hạn và hoàn toàn tốt đẹp pavpanchekha, bạn có thể sử dụng một biểu thức máy phát điện (một danh sách comprehensions chỉ là một biểu hiện phát thức ăn cho các nhà xây dựng danh sách - nó thực sự mạnh hơn und phổ quát) cho thêm sự tốt lành:

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

Ngoài việc thực sự mát mẻ và chức năng, nó cũng là một thuật toán tốt hơn: Trừ khi thi hành dict là especiall y ngu ngốc (không được coi là một built-in), điều này sẽ tiêu thụ cùng một lượng bộ nhớ cho mọi kích thước của l (tức là chạy trong không đổi O (1) không gian) vì nó xử lý một cặp tại một thời điểm thay vì tạo một danh sách toàn bộ các bộ dữ liệu mới đầu tiên.

5

Một cơ hội tốt đẹp để hiển thị yêu thích thành ngữ python của tôi:

>>> S = [1,2,3,4,5,6] 
>>> dict(zip(*[iter(S)]*2)) 
{1: 2, 3: 4, 5: 6} 

Đó là dòng khéo léo qua hai đối số để zip() nơi mỗi đối số là cùng iterator qua S. zip() tạo tuples 2 mục, kéo từ trình vòng lặp qua zip mỗi lần. dict() sau đó chuyển đổi những bộ dữ liệu đó thành một từ điển.

Để suy luận:

S = [1,2,3,4,5,6] 

I = iter(S) 
dict(zip(I,I)) 
+1

TUYỆT VỜI. Điểm brownie lớn! – katrielalex

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