จะลบคีย์ออกจากพจนานุกรม Python ได้อย่างไร


1764

เมื่อลบคีย์ออกจากพจนานุกรมฉันใช้:

if 'key' in my_dict:
    del my_dict['key']

มีวิธีหนึ่งในการทำเช่นนี้?


24
สคริปต์มาตรฐานสำหรับวิธีการต่างๆที่เสนอในคำตอบสำหรับคำถามนี้: gist.github.com/zigg/6280653
zigg

คำตอบ:


2837

หากต้องการลบคีย์โดยไม่คำนึงว่าอยู่ในพจนานุกรมหรือไม่ให้ใช้รูปแบบสองอาร์กิวเมนต์ของdict.pop():

my_dict.pop('key', None)

สิ่งนี้จะกลับมาmy_dict[key]หากkeyมีอยู่ในพจนานุกรมและNoneอื่น ๆ หากไม่ได้ระบุพารามิเตอร์ที่สอง (เช่น. my_dict.pop('key')) และkeyไม่มีอยู่KeyErrorจะมีการยกระดับ

หากต้องการลบคีย์ที่รับประกันว่ามีอยู่คุณสามารถใช้

del my_dict['key']

นี่จะเป็นการเพิ่ม a KeyErrorหากคีย์ไม่ได้อยู่ในพจนานุกรม


152
บางครั้งข้อได้เปรียบของการใช้pop()เกินdel: มันส่งคืนค่าสำหรับคีย์นั้น วิธีนี้คุณสามารถรับและลบรายการจาก dict ในบรรทัดเดียว
kratenko

7
ในคำถามไม่จำเป็นต้องเก็บค่าไว้ สิ่งนี้จะเพิ่มความซับซ้อนที่ไม่จำเป็นเท่านั้น คำตอบจาก @zigg (ด้านล่าง) ดีกว่ามาก
Salvatore Cosentino

10
@SalvatoreCosentino ฉันไม่สามารถทำตามอาร์กิวเมนต์ของคุณ รหัสในคำตอบนี้ซับซ้อนกว่าโค้ดในคำตอบอื่น ๆ อย่างไร
Sven Marnach

33
@SalvatoreCosentino ไม่ละเว้นการส่งคืนค่าของฟังก์ชันที่ไม่มีประสิทธิภาพเลย ค่อนข้างตรงกันข้าม - วิธีนี้เร็วกว่าtry/ exceptวิธีแก้ปัญหาหากไม่มีคีย์ คุณอาจพบว่าอ่านอย่างใดอย่างหนึ่งได้ง่ายขึ้นซึ่งก็ดี ทั้งคู่เป็น Python ที่ใช้สำนวนดังนั้นเลือกสิ่งที่คุณต้องการ แต่การอ้างว่าคำตอบนี้ซับซ้อนหรือไม่มีประสิทธิภาพก็ไม่สมเหตุสมผล
Sven Marnach

5
@ user5359531 ฉันไม่เข้าใจ ปัญหานี้เป็นอย่างไร ไม่มีวิธีการใด ๆ สำหรับประเภทในตัวของ Python ที่ส่งคืนselfดังนั้นจึงค่อนข้างน่าแปลกใจถ้าวิธีนี้ทำ
Sven Marnach

352

คำตอบเฉพาะ "มีวิธีหนึ่งในการทำเช่นนี้หรือไม่?"

if 'key' in my_dict: del my_dict['key']

... ดีคุณถาม ;-)

คุณควรพิจารณาได้ว่าวิธีการลบวัตถุจากหนึ่งนี้dictคือไม่อะตอม -IT เป็นไปได้ว่า'key'อาจจะอยู่ในmy_dictระหว่างifคำสั่ง แต่อาจถูกลบออกก่อนที่delจะดำเนินการในกรณีที่จะล้มเหลวด้วยdel KeyErrorป.ร. ให้ไว้ ณ ที่นี้มันจะปลอดภัยที่สุดที่จะใช้dict.popหรือบางสิ่งบางอย่างตามแนวของ

try:
    del my_dict['key']
except KeyError:
    pass

ซึ่งแน่นอนไม่แน่นอนหนึ่งซับ


27
ใช่popเป็นข้อสรุปที่แน่นอนมากขึ้นแม้ว่าจะมีข้อได้เปรียบที่สำคัญข้อหนึ่งในการทำเช่นนี้: มันชัดเจนทันทีว่าทำอะไรอยู่
zigg

4
try/exceptคำสั่งที่มีราคาแพงมากขึ้น การเพิ่มข้อยกเว้นช้า
Chris Barker

16
@ChrisBarker ฉันพบว่ามีกุญแจอยู่หรือไม่tryก็เร็วกว่าเล็กน้อยแม้ว่ามันจะไม่ได้tryก็ตาม popค่อนข้างสอดคล้อง แต่ช้ากว่าทั้งหมด แต่tryใช้รหัสที่ไม่ปรากฏ ดูgist.github.com/zigg/6280653 ท้ายที่สุดมันขึ้นอยู่กับความถี่ที่คุณคาดหวังว่ากุญแจจะอยู่ในพจนานุกรมหรือไม่และคุณต้องการอะตอมมิกหรือไม่และแน่นอนว่าคุณมีส่วนร่วมในการปรับให้เหมาะสมก่อนกำหนดหรือไม่?
zigg

9
ฉันเชื่อว่าคุณค่าของความชัดเจนไม่ควรมองข้าม +1 สำหรับสิ่งนี้
Juan Carlos Coto

2
เกี่ยวกับค่าใช้จ่ายของลอง / if 'key' in mydict: #then del...ยกเว้นคุณยังสามารถไป ฉันต้องการดึงคีย์ / วาลจาก dict เพื่อแยกอย่างถูกต้องป๊อปไม่ใช่โซลูชันที่สมบูรณ์แบบ
Marc

152

ฉันใช้เวลาพอจะเข้าใจว่าmy_dict.pop("key", None)กำลังทำอะไรอยู่ ดังนั้นฉันจะเพิ่มนี่เป็นคำตอบเพื่อประหยัดเวลาผู้ใช้ Google:

pop(key[, default])

หากที่สำคัญคือในพจนานุกรมเอามันและส่งกลับค่าอื่นกลับมาเริ่มต้น หากไม่ได้กำหนดค่าเริ่มต้นและรหัสไม่ได้อยู่ในพจนานุกรมKeyErrorจะมีการยกระดับขึ้น

เอกสาร


15
เพียงพิมพ์ความช่วยเหลือ (dict.pop) ในล่ามไพ ธ อน
David Mulder

13
ช่วย () และ dir () สามารถเป็นเพื่อนของคุณได้เมื่อคุณต้องการรู้ว่ามีอะไรทำ
David Mulder

3
หรือdict.pop?ใน IPython
Erik Kaplun

50

del my_dict[key]เร็วกว่าmy_dict.pop(key)การลบคีย์ออกจากพจนานุกรมเล็กน้อยเมื่อมีคีย์อยู่

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

แต่เมื่อที่สำคัญไม่ได้อยู่ที่จะเร็วกว่าเล็กน้อยif key in my_dict: del my_dict[key] my_dict.pop(key, None)ทั้งสองอย่างนี้เร็วกว่าสามครั้งdelใน a try/ exceptstatement:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
การวัดการกำหนดเวลาของการดำเนินการที่รวดเร็วนั้นค่อนข้างโง่ รหัสของคุณอาจจะไม่ได้ไปรับได้เร็วขึ้นมากเพราะคุณเปลี่ยนไปpop delการสร้างพจนานุกรมจะแคระการลบสิ่งต่าง ๆ อย่างสมบูรณ์
บอริส

1
@ Boris - นี่เป็นประโยชน์เช่นเดียวกับการออกกำลังกายทั่วไป
เดซี่

1
@daisy สิ่งที่ฉันพูดคือคุณควรเลือกวากยสัมพันธ์ที่อ่านง่ายที่สุดไม่ใช่การดำเนินการที่เร็วกว่า 300 นาโนวินาที (นั่นคือความแตกต่างระหว่างdelและpopจากการตั้งเวลาครั้งแรกด้านบน)
Boris

นอกจากนี้การดำเนินการเหล่านี้ยังเร็วมากจนเวลาเหล่านี้ไม่น่าเชื่อถือ
บอริส

45

หากคุณต้องการลบคีย์จำนวนมากออกจากพจนานุกรมในรหัสหนึ่งบรรทัดฉันคิดว่าการใช้ map () ค่อนข้างสั้นและสามารถอ่าน Pythonic ได้:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

และหากคุณต้องการตรวจจับข้อผิดพลาดที่คุณเติมค่าที่ไม่ได้อยู่ในพจนานุกรมให้ใช้แลมบ์ดาในแผนที่ () ดังนี้:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

หรือในpython3คุณต้องใช้รายการความเข้าใจแทน:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

มันได้ผล. และ 'e' ไม่ได้ทำให้เกิดข้อผิดพลาดแม้ว่า myDict จะไม่มีรหัส 'e'


42
สิ่งนี้จะไม่ทำงานใน Python 3 เพราะmapตอนนี้เพื่อน ๆ ขี้เกียจแล้วก็ส่งคืนตัววนซ้ำ การใช้mapผลข้างเคียงโดยทั่วไปถือว่าแย่ for ... inห่วงมาตรฐานจะดีกว่า ดูการดูและการวนซ้ำแทนรายการสำหรับข้อมูลเพิ่มเติม
Greg Krimer

5
โดยไม่คำนึงถึงรสนิยมและรูปแบบการฝึกความเข้าใจในรายการควรยังคงทำงานใน Py3 [myDict.pop(i, None) for i in ['a', 'c']]เนื่องจากเป็นทางเลือกทั่วไปสำหรับmap(และfilter)
Michael Ekoka

@MichaelEkoka คุณไม่ควรใช้ความเข้าใจในรายการสำหรับผลข้างเคียงของพวกเขาใช้for ... inลูปปกติ
Boris

@ Boris คุณอาจพูดถูก คำตอบของฉันเกี่ยวข้องกับการใช้โดยmap()เฉพาะซึ่งมักใช้กับผลข้างเคียง ทางเลือกที่แนะนำใน Python คือความเข้าใจในรายการซึ่งในความคิดของฉันยังอ่านได้ค่อนข้างเบาและมีความรู้ความเข้าใจในฐานะหนึ่งซับ (ดูคำถาม) ใช้สำหรับผลข้างเคียงเท่านั้นทั้งคู่สร้างผลลัพธ์ในรายการที่ไร้ประโยชน์ซึ่งอาจไม่มีประสิทธิภาพ ในฐานะของ Python3 loop(d.pop(k) for k in ['a', 'b'])ผมไม่ได้ตระหนักถึงในตัวฟังก์ชั่นที่สามารถได้อย่างปลอดภัยและสวยงามย้ำผ่านการแสดงออกเครื่องกำเนิดไฟฟ้าโดยไม่ต้องเสียค่าใช้จ่ายผลพลอยได้เช่น
Michael Ekoka

ฉันขบขันที่คำตอบที่ถูกโหวตสูงสุดตลอดกาลของฉันรวมถึงแฮ็กที่ฉันไม่เคยใช้ ความเข้าใจในรายการ (ตัวเลือก 3) เป็นวิธีที่แย่ที่สุดในความคิดของฉัน ใช้อันนั้น
Marc Maxmeister

19

คุณสามารถใช้ความเข้าใจในพจนานุกรมเพื่อสร้างพจนานุกรมใหม่โดยลบคีย์นั้น:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

คุณสามารถลบได้ตามเงื่อนไข ไม่มีข้อผิดพลาดหากkeyไม่มีอยู่



7

เราสามารถลบคีย์ออกจากพจนานุกรม Python ได้ด้วยวิธีการต่อไปนี้

ใช้delคำหลัก; มันเกือบจะเป็นวิธีเดียวกันกับที่คุณทำ -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

หรือ

เราสามารถทำสิ่งต่อไปนี้:

แต่เราควรจำไว้ว่าในกระบวนการนี้จริง ๆ แล้วมันจะไม่ลบคีย์ใด ๆ จากพจนานุกรมแทนที่จะสร้างคีย์เฉพาะที่แยกออกจากพจนานุกรมนั้น myDictนอกจากนี้ผมสังเกตเห็นว่ามันกลับพจนานุกรมซึ่งไม่ได้รับคำสั่งเช่นเดียวกับ

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

ถ้าเราใช้มันในเปลือกก็จะดำเนินการบางอย่างเช่น{'five': 500, 'four': 400, 'three': 300, 'two': 200}- myDictแจ้งให้ทราบว่ามันเป็นไม่เหมือนกันสั่ง ถ้าเราลองพิมพ์อีกครั้งmyDictเราจะเห็นปุ่มทั้งหมดรวมถึงที่เราแยกออกจากพจนานุกรมด้วยวิธีการนี้ อย่างไรก็ตามเราสามารถสร้างพจนานุกรมใหม่โดยกำหนดคำสั่งต่อไปนี้ลงในตัวแปร:

var = {key:value for key, value in myDict.items() if key != 'one'}

ตอนนี้ถ้าเราพยายามที่จะพิมพ์มันก็จะทำตามคำสั่งของผู้ปกครอง:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

หรือ

ใช้pop()วิธีการ

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

ความแตกต่างระหว่างdelกับpopคือว่าโดยใช้pop()วิธีการเราสามารถจัดเก็บค่าของคีย์ถ้าจำเป็นเช่นต่อไปนี้:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

แยกส่วนสำคัญนี้เพื่อใช้อ้างอิงในอนาคตหากคุณพบว่ามีประโยชน์


1
อย่าใช้if myDict.get('one')เพื่อตรวจสอบว่ามีกุญแจอยู่หรือไม่! มันจะล้มเหลวหาก myDict ['one'] มีค่าที่ไม่ถูกต้อง นอกจากนี้ dicts ไม่มีลำดับโดยธรรมชาติดังนั้นจึงไม่มีความเหมาะสมที่จะพูดถึง
Rob

@Rob dicts ได้รับคำสั่งจากคำสั่งแทรกเริ่มต้นด้วย CPython 3.6 และการใช้งาน Python อื่น ๆ ทั้งหมดที่เริ่มต้นด้วย 3.7
บอริส

4

คุณสามารถใช้การจัดการข้อยกเว้นถ้าคุณต้องการที่จะ verbose มาก:

try: 
    del dict[key]

except KeyError: pass

สิ่งนี้ช้าลงกว่าpop()วิธีหากคีย์ไม่มีอยู่

my_dict.pop('key', None)

มันจะไม่สำคัญกับคีย์สองสามปุ่ม แต่ถ้าคุณทำสิ่งนี้ซ้ำ ๆ วิธีหลังเป็นวิธีที่ดีกว่า

วิธีที่เร็วที่สุดคือ:

if 'key' in dict: 
    del myDict['key']

แต่วิธีการนี้เป็นอันตรายเพราะถ้า'key'ถูกลบระหว่างสองบรรทัดKeyErrorจะเพิ่มขึ้น


1

ฉันชอบเวอร์ชั่นที่ไม่เปลี่ยนรูป

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

อีกวิธีคือการใช้ items () + dict comprehension

items () ควบคู่ไปกับความเข้าใจ dict ยังสามารถช่วยให้เราบรรลุภารกิจการลบคู่คีย์ - ค่า แต่มันมีข้อเสียเปรียบที่ไม่ใช่เทคนิค dict แบบ inplace จริงแล้วเป็น dict ใหม่หากสร้างขึ้นยกเว้นคีย์ที่เราไม่ต้องการรวมไว้

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

เอาท์พุท:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

ตัวกรองเดี่ยวบนกุญแจ

  • ส่งคืน "key" และลบออกจาก my_dict หากมี "key" อยู่ใน my_dict
  • คืนค่า None ถ้าไม่มี "key" ใน my_dict

สิ่งนี้จะเปลี่ยนแปลงmy_dictในสถานที่ (ไม่แน่นอน)

my_dict.pop('key', None)

ตัวกรองหลายตัวบนกุญแจ

สร้าง dict ใหม่ (ไม่เปลี่ยนรูป)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.