Hãy xem xét từ điển sau, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Tôi muốn trả về cặp khóa N đầu tiên: giá trị từ d (N <= 4 trong trường hợp này). Phương pháp hiệu quả nhất để làm điều này là gì?
Hãy xem xét từ điển sau, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Tôi muốn trả về cặp khóa N đầu tiên: giá trị từ d (N <= 4 trong trường hợp này). Phương pháp hiệu quả nhất để làm điều này là gì?
Câu trả lời:
Không có điều gì như vậy một "n phím đầu tiên" bởi vì a dict
không nhớ khóa nào đã được đưa vào đầu tiên.
Tuy nhiên, bạn có thể nhận được n cặp khóa-giá trị bất kỳ :
n_items = take(n, d.iteritems())
Điều này sử dụng việc triển khai take
từ các itertools
công thức :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
Xem nó hoạt động trực tuyến: Ideone
Cập nhật cho Python 3.6
n_items = take(n, d.items())
iteritems
nên được thay thế bằng items
cho folks trên Python 3
take()
một phần của cơ sở mã python ở đâu? Hoặc, nó hoàn toàn là chức năng bạn đã xác định trong câu trả lời của mình ở đây? Hỏi như thể đó là một phần của cơ sở mã, tôi không thể tìm / nhập nó. :)
Một cách rất hiệu quả để truy xuất bất cứ thứ gì là kết hợp danh sách hoặc từ điển hiểu được với việc cắt. Nếu bạn không cần sắp xếp các mục (bạn chỉ muốn n cặp ngẫu nhiên), bạn có thể sử dụng cách hiểu từ điển như sau:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Nói chung, một cách hiểu như thế này luôn chạy nhanh hơn vòng lặp "for x in y" tương đương. Ngoài ra, bằng cách sử dụng .keys () để tạo danh sách các khóa từ điển và cắt danh sách đó, bạn tránh 'chạm vào' bất kỳ khóa không cần thiết nào khi tạo từ điển mới.
Nếu bạn không cần khóa (chỉ các giá trị), bạn có thể sử dụng cách hiểu danh sách:
first2vals = [v for v in mydict.values()[:2]]
Nếu bạn cần các giá trị được sắp xếp dựa trên khóa của chúng, thì không có gì rắc rối hơn:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
hoặc nếu bạn cũng cần chìa khóa:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
Các Python dict
không được sắp xếp theo thứ tự, vì vậy việc yêu cầu các phím "N đầu tiên" là vô nghĩa.
Các collections.OrderedDict
lớp hiện có sẵn nếu đó là những gì bạn cần. Bạn có thể có được bốn yếu tố đầu tiên một cách hiệu quả là
import itertools
import collections
d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)
for key, value in x:
print key, value
itertools.islice
cho phép bạn lấy một phần tử từ bất kỳ trình vòng lặp nào một cách lười biếng. Nếu bạn muốn kết quả có thể sử dụng lại được, bạn cần chuyển đổi nó thành một danh sách hoặc một cái gì đó, như sau:
x = list(itertools.islice(d.items(), 0, 4))
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
print(next(iterator))
Về cơ bản, biến chế độ xem (dict_items) thành một trình lặp, rồi lặp lại nó với next ().
Không thấy nó trên đây. Sẽ không được sắp xếp theo thứ tự nhưng là cú pháp đơn giản nhất nếu bạn chỉ cần lấy một số phần tử từ từ điển.
n = 2
{key:value for key,value in d.items()[0:n]}
TypeError: 'dict_items' object is not subscriptable
{key:value for key,value in stocks.items()[0:n]}
(cổ phiếu là tên của từ điển của tôi)
Để lấy N phần tử hàng đầu từ từ điển python của bạn, người ta có thể sử dụng dòng mã sau:
list(dictionaryName.items())[:N]
Trong trường hợp của bạn, bạn có thể thay đổi nó thành:
list(d.items())[:4]
Xem PEP 0265 về phân loại từ điển. Sau đó, sử dụng mã có thể lặp lại nói trên.
Nếu bạn cần hiệu quả hơn trong các cặp khóa-giá trị đã được sắp xếp. Sử dụng một cấu trúc dữ liệu khác. Đó là, một thứ duy trì thứ tự được sắp xếp và các liên kết khóa-giá trị.
Ví dụ
import bisect
kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))
print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
trong py3, điều này sẽ thực hiện thủ thuật
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Điều này phụ thuộc vào điều gì là 'hiệu quả nhất' trong trường hợp của bạn.
Nếu bạn chỉ muốn một mẫu bán ngẫu nhiên của một từ điển khổng lồ foo
, hãy sử dụng foo.iteritems()
và lấy nhiều giá trị từ nó khi bạn cần, đó là một thao tác lười biếng nhằm tránh tạo danh sách khóa hoặc mục rõ ràng.
Nếu bạn cần sắp xếp các khóa trước tiên, không có cách nào khác là sử dụng một cái gì đó như keys = foo.keys(); keys.sort()
hoặc sorted(foo.iterkeys())
, bạn sẽ phải xây dựng một danh sách các khóa rõ ràng. Sau đó cắt hoặc lặp qua N đầu tiên keys
.
BTW tại sao bạn quan tâm đến cách 'hiệu quả'? Bạn đã lập hồ sơ cho chương trình của mình? Nếu không, hãy sử dụng cách rõ ràng và dễ hiểu trước. Rất có thể nó sẽ hoạt động khá tốt mà không trở thành điểm nghẽn.
Bạn có thể tiếp cận điều này theo một số cách. Nếu thứ tự quan trọng, bạn có thể làm điều này:
for key in sorted(d.keys()):
item = d.pop(key)
Nếu đơn đặt hàng không phải là mối quan tâm, bạn có thể làm điều này:
for i in range(4):
item = d.popitem()
value
hơn là item
cho rõ ràng.
Từ điển không có thứ tự, vì vậy trước khi chọn N cặp giá trị khóa hàng đầu, hãy sắp xếp nó.
import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values
Bây giờ chúng ta có thể thực hiện việc truy xuất các phần tử 'N' hàng đầu :, bằng cách sử dụng cấu trúc phương thức như sau:
def return_top(elements,dictionary_element):
'''Takes the dictionary and the 'N' elements needed in return
'''
topers={}
for h,i in enumerate(dictionary_element):
if h<elements:
topers.update({i:dictionary_element[i]})
return topers
để lấy 2 phần tử hàng đầu thì chỉ cần sử dụng cấu trúc này:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)
coi một mệnh lệnh
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice sẽ thực hiện thủ thuật :) hy vọng nó sẽ giúp!
Điều này có thể không được thanh lịch cho lắm, nhưng phù hợp với tôi:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x= 0
for key, val in d.items():
if x == 2:
break
else:
x += 1
# Do something with the first two key-value pairs
Tôi đã thử một số câu trả lời ở trên và lưu ý rằng một số câu trả lời phụ thuộc vào phiên bản và không hoạt động trong phiên bản 3.7.
Tôi cũng lưu ý rằng kể từ 3.6, tất cả các từ điển đều được sắp xếp theo trình tự mà các mục được chèn vào.
Mặc dù các từ điển đã được sắp xếp thứ tự kể từ ngày 3.6, một số câu lệnh mà bạn mong đợi làm việc với các cấu trúc có thứ tự dường như không hoạt động.
Câu trả lời cho câu hỏi OP phù hợp nhất với tôi.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
list(d.items())[:4]
. list () là cách triển khai cơ bản cho nhiều câu trả lời.