พิจารณาพจนานุกรมต่อไปนี้ d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
ฉันต้องการส่งคืนคู่คีย์ N แรก: ค่าจาก d (N <= 4 ในกรณีนี้) วิธีใดที่มีประสิทธิภาพที่สุดในการทำเช่นนี้?
พิจารณาพจนานุกรมต่อไปนี้ d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
ฉันต้องการส่งคืนคู่คีย์ N แรก: ค่าจาก d (N <= 4 ในกรณีนี้) วิธีใดที่มีประสิทธิภาพที่สุดในการทำเช่นนี้?
คำตอบ:
ไม่มีคีย์ "n ตัวแรก" แบบนี้เนื่องจาก a dict
จำไม่ได้ว่าคีย์ใดถูกแทรกก่อน
คุณสามารถรับn คู่คีย์ - ค่าใดก็ได้แม้ว่า:
n_items = take(n, d.iteritems())
สิ่งนี้ใช้การใช้งานtake
จากitertools
สูตรอาหาร :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
ดูการทำงานออนไลน์: ideone
อัปเดตสำหรับ Python 3.6
n_items = take(n, d.items())
iteritems
ควรถูกแทนที่ด้วยitems
สำหรับคนใน Python 3
take()
ส่วนหนึ่งของฐานรหัสหลามทุกที่หรือไม่? หรือเป็นฟังก์ชันที่คุณกำหนดไว้ในคำตอบของคุณที่นี่เท่านั้น? ถามราวกับว่าเป็นส่วนหนึ่งของฐานรหัสฉันไม่สามารถค้นหา / นำเข้าได้ :)
takewhile
ใน python 3.8 devdocs.io/python~3.8/library/itertools#itertools.take ในขณะเดียวกัน
วิธีที่มีประสิทธิภาพมากในการดึงข้อมูลคือการรวมความเข้าใจของรายการหรือพจนานุกรมเข้ากับการแบ่งส่วน หากคุณไม่จำเป็นต้องสั่งซื้อสินค้า (คุณต้องการเพียง n คู่แบบสุ่ม) คุณสามารถใช้ความเข้าใจในพจนานุกรมดังนี้:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
โดยทั่วไปความเข้าใจเช่นนี้จะทำงานได้เร็วกว่าลูป "สำหรับ x ใน y" ที่เทียบเท่าเสมอ นอกจากนี้การใช้ .keys () เพื่อสร้างรายการคีย์พจนานุกรมและการแบ่งส่วนรายการนั้นคุณจะหลีกเลี่ยงการ 'แตะ' คีย์ที่ไม่จำเป็นเมื่อคุณสร้างพจนานุกรมใหม่
หากคุณไม่ต้องการคีย์ (เฉพาะค่า) คุณสามารถใช้การทำความเข้าใจรายการ:
first2vals = [v for v in mydict.values()[:2]]
หากคุณต้องการค่าที่เรียงตามคีย์ของพวกเขาก็ไม่มีปัญหามากขึ้น:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
หรือหากคุณต้องการกุญแจเช่นกัน:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
dict
ไม่ได้เรียงลำดับ s ของ Python ดังนั้นจึงไม่มีความหมายที่จะขอคีย์ "N แรก"
collections.OrderedDict
ชั้นสามารถใช้ได้ถ้านั่นคือสิ่งที่คุณต้องการ คุณสามารถรับสี่องค์ประกอบแรกได้อย่างมีประสิทธิภาพเป็น
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
ช่วยให้คุณใช้ชิ้นส่วนขององค์ประกอบจากตัววนซ้ำใด ๆ ได้อย่างเกียจคร้าน หากคุณต้องการให้ผลลัพธ์สามารถนำกลับมาใช้ใหม่ได้คุณจะต้องแปลงเป็นรายการหรือบางอย่างเช่น:
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))
โดยทั่วไปเปลี่ยนมุมมอง (dict_items) เป็นตัววนซ้ำจากนั้นทำซ้ำด้วย next ()
ไม่เห็นบนนี้ จะไม่ถูกเรียงลำดับ แต่เป็นไวยากรณ์ที่ง่ายที่สุดหากคุณต้องการเพียงแค่นำองค์ประกอบบางอย่างจากพจนานุกรม
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]}
(หุ้นเป็นชื่อพจนานุกรมของฉัน)
ในการรับองค์ประกอบ N อันดับต้น ๆ จากพจนานุกรม python ของคุณคุณสามารถใช้โค้ดบรรทัดต่อไปนี้:
list(dictionaryName.items())[:N]
ในกรณีของคุณคุณสามารถเปลี่ยนเป็น:
list(d.items())[:4]
ดูPEP 0265ในพจนานุกรมการเรียงลำดับ จากนั้นใช้รหัสทำซ้ำดังกล่าวข้างต้น
หากคุณต้องการประสิทธิภาพที่มากขึ้นในคู่คีย์ - ค่าที่เรียงลำดับ ใช้โครงสร้างข้อมูลอื่น นั่นคือสิ่งที่รักษาการเรียงลำดับและการเชื่อมโยงคีย์ - ค่า
เช่น
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)]
ใน py3 นี่จะทำเคล็ดลับ
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
เพียงเพิ่มคำตอบโดยใช้ zip
{k: d[k] for k, _ in zip(d, range(n))}
ขึ้นอยู่กับสิ่งที่ 'มีประสิทธิภาพสูงสุด' ในกรณีของคุณ
หากคุณต้องการเพียงแค่ตัวอย่างกึ่งสุ่มของพจนานุกรมขนาดใหญ่foo
ให้ใช้foo.iteritems()
และรับค่าจากมันมากเท่าที่คุณต้องการมันเป็นการดำเนินการที่ขี้เกียจที่จะหลีกเลี่ยงการสร้างรายการคีย์หรือรายการที่ชัดเจน
หากคุณต้องการจัดเรียงคีย์ก่อนไม่มีวิธีใดที่จะใช้สิ่งที่เหมือนkeys = foo.keys(); keys.sort()
หรือsorted(foo.iterkeys())
คุณจะต้องสร้างรายการคีย์ที่ชัดเจน keys
จากนั้นหั่นหรือย้ำผ่านครั้งแรกยังไม่มีข้อความ
BTW ทำไมคุณถึงสนใจวิธีที่ 'มีประสิทธิภาพ'? คุณทำโปรไฟล์โปรแกรมของคุณหรือไม่? หากคุณไม่เคยทำให้ใช้วิธีที่ชัดเจนและเข้าใจง่ายก่อน โอกาสที่จะทำได้ดีโดยไม่กลายเป็นคอขวด
สิ่งนี้อาจไม่สวยหรูมากนัก แต่ก็เหมาะกับฉัน:
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
คุณสามารถเข้าถึงวิธีนี้ได้หลายวิธี หากคำสั่งซื้อมีความสำคัญคุณสามารถทำได้:
for key in sorted(d.keys()):
item = d.pop(key)
หากคำสั่งซื้อไม่เป็นปัญหาคุณสามารถทำได้:
for i in range(4):
item = d.popitem()
value
มากกว่าitem
เพื่อความชัดเจน
พจนานุกรมจะไม่มีลำดับดังนั้นก่อนที่จะเลือกคู่ค่าคีย์ 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
ตอนนี้เราสามารถดึงองค์ประกอบ 'N' ด้านบนได้แล้วโดยใช้โครงสร้างวิธีการดังนี้:
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
เพื่อให้ได้องค์ประกอบ 2 อันดับแรกจากนั้นใช้โครงสร้างนี้:
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)
สำหรับ Python 3 ขึ้นไปให้เลือก n คู่แรก
n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}
พิจารณาคำสั่ง
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice จะทำเคล็ดลับ :) หวังว่ามันจะช่วยได้!
ฉันได้ลองคำตอบสองสามข้อด้านบนแล้วและทราบว่าบางคำตอบขึ้นอยู่กับเวอร์ชันและไม่สามารถใช้งานได้ในเวอร์ชัน 3.7
ฉันทราบด้วยว่าตั้งแต่ 3.6 พจนานุกรมทั้งหมดจะเรียงลำดับตามลำดับที่แทรกรายการ
แม้จะมีการสั่งพจนานุกรมตั้งแต่ 3.6 ข้อความบางส่วนที่คุณคาดว่าจะใช้กับโครงสร้างที่สั่งได้ก็ดูเหมือนจะไม่ได้ผล
คำตอบสำหรับคำถาม OP ที่ได้ผลดีที่สุดสำหรับฉัน
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
def GetNFirstItems(self):
self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
self.get_items = int(input())
for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
if self.index==self.get_items:
break
else:
print(self.item,",",end="")
วิธีการที่ผิดปกติเนื่องจากให้ความซับซ้อนของเวลา O (N) ที่เข้มข้น
list(d.items())[:4]
การทดสอบของฉันแสดงไม่ได้เป็นทางออกเดียวที่จะเร็วกว่า list () คือการนำไปใช้งานสำหรับหลาย ๆ คำตอบ