ลบรายการออกจากพจนานุกรมเมื่อไม่ทราบรหัส


112

วิธีที่ดีที่สุดในการลบรายการออกจากพจนานุกรมตามค่าคือเมื่อไม่ทราบคีย์ของรายการใด นี่เป็นแนวทางง่ายๆ:

for key, item in some_dict.items():
    if item is item_to_remove:
        del some_dict[key]

มีวิธีที่ดีกว่านี้ไหม มีอะไรผิดปกติกับการกลายพันธุ์ (ลบรายการ) จากพจนานุกรมในขณะที่ทำซ้ำหรือไม่


1
เหตุผลที่ขีดเส้นใต้ในการห้ามมิให้เปลี่ยนคำสั่งในขณะที่ทำซ้ำเนื่องจากภายในมีคำสั่งให้ทำซ้ำหากคุณกลายพันธุ์คีย์คำสั่งจะถูกบั่นทอนซึ่งส่งผลให้เกิดพฤติกรรมที่ไม่รู้จัก
Spectral

คำตอบ:


92

โปรดทราบว่าคุณกำลังทดสอบข้อมูลประจำตัวของอ็อบเจ็กต์อยู่ ( isจะส่งคืนก็ต่อTrueเมื่อตัวถูกดำเนินการทั้งสองถูกแสดงโดยอ็อบเจ็กต์เดียวกันในหน่วยความจำซึ่งไม่ได้เป็นเช่นนั้นกับอ็อบเจ็กต์สองตัวที่เปรียบเทียบเท่ากัน==เสมอไป) หากคุณกำลังทำสิ่งนี้โดยตั้งใจคุณสามารถเขียนรหัสของคุณใหม่เป็นไฟล์

some_dict = {key: value for key, value in some_dict.items() 
             if value is not value_to_remove}

แต่อาจไม่ทำในสิ่งที่คุณต้องการ:

>>> some_dict = {1: "Hello", 2: "Goodbye", 3: "You say yes", 4: "I say no"}
>>> value_to_remove = "You say yes"
>>> some_dict = {key: value for key, value in some_dict.items() if value is not value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 3: 'You say yes', 4: 'I say no'}
>>> some_dict = {key: value for key, value in some_dict.items() if value != value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 4: 'I say no'}

ดังนั้นคุณอาจต้องการแทน!=is not


2
นั่นคือการบีบอัดพจนานุกรมหรือไม่? พวกเขาถูกเพิ่มเมื่อใด
ปุ่ม 840

4
คุณสามารถใช้some_dict.iteritems()ที่นี่และใส่forและifคำสั่งในบรรทัดแยกกันเพื่อให้อ่านง่าย
jfs

3
ฉันเชื่อว่ามีการเพิ่มความเข้าใจพจนานุกรมใน Python 2.7
มิ ธ รันดี

2
@JF เซบาสเตียน: ฉันหลาม 3 และอยู่ในขณะนี้iteritems itemsใน Python 2.7 iteritems()นั้นดีกว่าแน่นอน
Tim Pietzcker

1
@ Buttons840 พวกเขาจะเรียกcomprehensions Dict ใน PEP 274หรือแสดงพจนานุกรม ตามที่ PEP กล่าวว่าพวกเขาถูกเพิ่มใน 2.7เป็นเพลง 3.x backported หรือคุณสามารถป้อนdict()ด้วยนิพจน์ตัวสร้างที่เหมาะสมซึ่งก็คือ 2.4 meta: สามารถเรียกดู peps ได้ที่นี่เพื่อค้นหาสิ่งต่างๆ
n611x007

120

dict.pop(key[, default])วิธีช่วยให้คุณลบรายการเมื่อคุณรู้ว่ากุญแจสำคัญ defaultก็จะส่งกลับค่าที่สำคัญถ้ามันจะเอารายการมิฉะนั้นก็จะส่งกลับสิ่งที่จะถูกส่งเป็น ดูเอกสาร '

ตัวอย่าง:

>>> dic = {'a':1, 'b':2}
>>> dic
{'a': 1, 'b': 2}
>>> dic.pop('c', 0)
0
>>> dic.pop('a', 0)
1
>>> dic
{'b': 2}

4
OP ถามเกี่ยวกับเมื่อไม่ทราบคีย์
nmz787


42

การเปรียบเทียบอย่างง่ายระหว่างdelและpop () :

import timeit
code = """
results = {'A': 1, 'B': 2, 'C': 3}
del results['A']
del results['B']
"""
print timeit.timeit(code, number=100000)
code = """
results = {'A': 1, 'B': 2, 'C': 3}
results.pop('A')
results.pop('B')
"""
print timeit.timeit(code, number=100000)

ผลลัพธ์:

0.0329667857143
0.0451040902256

ดังนั้นเดลจะเร็วกว่าป๊อป ()


6
อย่างไรก็ตามความแตกต่างของประสิทธิภาพนั้นไม่มากและหากคุณต้องการหลีกเลี่ยงการเพิ่มข้อยกเว้นคุณสามารถระบุอาร์กิวเมนต์ที่สองให้กับpop()(ตามที่ @ n-1-1 ทำด้านบน) ซึ่งไม่ใช่ตัวเลือกสำหรับตัวdelดำเนินการ
Alex Dupuy

1
เสริมคำถาม แต่ฉันก็พยายามที่จะเข้าใจtimeitเช่นกัน ขอบคุณสำหรับตัวอย่างที่ชัดเจนนี้
Adam_G

OP ถามเกี่ยวกับเมื่อไม่ทราบคีย์ คำตอบนี้ถือว่ากุญแจเป็นที่รู้จัก
Jean-François Corbett

7

items()ส่งคืนรายการและเป็นรายการที่คุณทำซ้ำดังนั้นการกลายพันธุ์ของ dict ในลูปจึงไม่สำคัญที่นี่ หากคุณใช้iteritems()แทนการเปลี่ยนคำสั่งในลูปจะเป็นปัญหาและเช่นเดียวกันสำหรับviewitems()ใน Python 2.7

ฉันไม่สามารถคิดวิธีที่ดีกว่าในการลบรายการออกจากการเขียนตามค่า


7

ฉันจะสร้างรายการคีย์ที่ต้องลบแล้วลบออก เป็นเรื่องง่ายมีประสิทธิภาพและหลีกเลี่ยงปัญหาใด ๆ เกี่ยวกับการทำซ้ำและการเปลี่ยนคำสั่งพร้อมกัน

keys_to_remove = [key for key, value in some_dict.iteritems()
                  if value == value_to_remove]
for key in keys_to_remove:
    del some_dict[key]

OP ถามเกี่ยวกับเมื่อไม่ทราบคีย์ คำตอบนี้ถือว่ากุญแจเป็นที่รู้จัก
Jean-François Corbett

2

c คือพจนานุกรมใหม่และ a คือพจนานุกรมต้นฉบับของคุณ {'z', 'w'} คือคีย์ที่คุณต้องการลบออกจาก a

c = {key:a[key] for key in a.keys() - {'z', 'w'}}

ตรวจสอบเพิ่มเติม: https://www.safaribooksonline.com/library/view/python-cookbook-3rd/9781449357337/ch01.html



0

ไม่มีอะไรผิดปกติกับการลบรายการออกจากพจนานุกรมในขณะที่ทำซ้ำตามที่คุณเสนอ ระวังเธรดหลายชุดโดยใช้พจนานุกรมเดียวกันในเวลาเดียวกันซึ่งอาจส่งผลให้เกิด KeyError หรือปัญหาอื่น ๆ

แน่นอนดูเอกสารได้ที่http://docs.python.org/library/stdtypes.html#typesmapping


for k,v in d.iteritems(): del d[k]RuntimeError: dictionary changed size during iterationจะให้ ดูคำอธิบายของ mithrandi
ปุ่ม 840

1
แน่นอนว่า d.iteritems () ไม่ใช่วิธีการทำซ้ำของโปสเตอร์ต้นฉบับไม่ใช่สิ่งที่ฉันอ้างถึงในคำตอบของฉัน
Thane Anthem

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.