ลบหลายรายการออกจากรายการ Python ด้วยคำสั่งเดียว


115

ใน python ฉันรู้วิธีลบรายการออกจากรายการ

item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)

โค้ดด้านบนนี้จะลบค่า 5 และ "item" ออกจาก item_list แต่พอมีเรื่องจะลบก็ต้องเขียนหลายบรรทัด

item_list.remove("something_to_remove")

ถ้าฉันรู้ดัชนีของสิ่งที่ฉันกำลังลบฉันใช้:

del item_list[x]

โดยที่ x คือดัชนีของรายการที่ฉันต้องการลบ

ถ้าฉันรู้ดัชนีของตัวเลขทั้งหมดที่ฉันต้องการลบฉันจะใช้การวนซ้ำบางอย่างกับdelรายการที่ดัชนี

แต่ถ้าฉันไม่ทราบดัชนีของรายการที่ต้องการลบล่ะ?

ฉันลองitem_list.remove('item', 'foo')แล้ว แต่ได้รับข้อผิดพลาดแจ้งว่าremoveใช้อาร์กิวเมนต์เดียวเท่านั้น

มีวิธีลบหลายรายการออกจากรายการในคำสั่งเดียวหรือไม่?

ปล. ผมเคยใช้delและremove. ใครสามารถอธิบายความแตกต่างระหว่างสองสิ่งนี้หรือเหมือนกัน

ขอบคุณ


1
ในการตอบคำถามที่สองของคุณ: delลบรายการตามดัชนี removeฟังก์ชั่นของรายการพบว่าดัชนีของรายการและเรียกdelในดัชนีที่
Aaron Christiansen

คำตอบ:


172

ใน Python การสร้างวัตถุใหม่มักจะดีกว่าการแก้ไขวัตถุที่มีอยู่:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

ซึ่งเทียบเท่ากับ:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
    if e not in ('item', 5):
        new_list.append(e)
item_list = new_list

ในกรณีที่มีรายการค่าที่กรองออกจำนวนมาก (ในที่('item', 5)นี้คือองค์ประกอบขนาดเล็ก) ให้ใช้ a setcan นำไปสู่การปรับปรุงประสิทธิภาพเนื่องจากการinดำเนินการอยู่ใน O (1):

item_list = [e for e in item_list if e not in {'item', 5}]

โปรดทราบว่าตามที่อธิบายไว้ในความคิดเห็นและแนะนำไว้ที่นี่สิ่งต่อไปนี้สามารถประหยัดเวลาได้มากขึ้นโดยหลีกเลี่ยงการตั้งค่าที่จะสร้างขึ้นในแต่ละลูป:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

กรองบานยังเป็นทางออกที่ดีถ้าหน่วยความจำไม่ได้ราคาถูก


ฉันชอบคำตอบแรก ฉันไม่ได้ทำรายการใหม่ซึ่งเป็นสิ่งที่ดี ขอบคุณ!
RandomCoder

ชุดนี้ได้รับการปรับให้เหมาะสมใน python 2 หรือปรับให้เหมาะสมใน python 3 เท่านั้น โดยที่ฉันหมายถึงชุดที่สร้างขึ้นเพียงครั้งเดียวเมื่อสร้าง bytecode?
ฮาร์

ชุดคือตามคำจำกัดความเหมาะสำหรับinการดำเนินการ ดูเกณฑ์มาตรฐานนี้สำหรับการเปรียบเทียบโครงสร้างข้อมูลดั้งเดิมทั้งสี่โครงสร้าง ใช่ชุดถูกสร้างขึ้นในแต่ละลูปตามที่แนะนำไว้ที่นี่ดังนั้นการบันทึกชุดในตัวแปรเฉพาะเพื่อใช้ในนิพจน์ตัวสร้างจะช่วยประหยัดเวลาได้
aluriak

@RandomCoder คุณสร้างรายการใหม่คุณแค่ใช้ชื่อซ้ำ คุณสามารถตรวจสอบโดยเปรียบเทียบก่อนและหลังid(item_list) item_list = [e for e in item_list if e not in ('item', 5)]ตรวจสอบคำตอบของฉันเพื่อดูวิธีแก้ไขรายการในสถานที่
Darkonaut

21
item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove=['item', 5, 'foo']

รายการสุดท้ายหลังจากลบควรเป็นดังนี้

final_list=[3.14, True]

รหัสบรรทัดเดียว

final_list= list(set(item_list).difference(set(list_to_remove)))

ผลลัพธ์จะเป็นดังนี้

final_list=[3.14, True]

13
ไม่มันจะสับเปลี่ยนรายการในรายการ ใช้เฉพาะในกรณีที่ลำดับรายการไม่สำคัญซึ่งมักจะทำบ่อย
scavenger

5
นอกจากนี้ยังจะลบรายการที่ซ้ำกันออกจากรายการ ไม่ใช่ว่าจะสำคัญสำหรับรายการตัวอย่าง
tschale

1
คำตอบนี้ไม่ถูกต้องและอาจทำให้เกิดข้อบกพร่องร้ายแรงเหตุใดจึงมีการโหวตเพิ่ม
omerfarukdogan

1
มันจะลบรายการที่ซ้ำกัน! คำตอบอาจทำให้เกิดข้อบกพร่องร้ายแรงโปรดอย่าใช้
user2698178

2

ฉันไม่รู้ว่าทำไมทุกคนถึงลืมพูดถึงความสามารถที่น่าทึ่งของsets ใน python คุณสามารถแคสต์รายการของคุณเป็นชุดจากนั้นลบสิ่งที่คุณต้องการลบออกด้วยนิพจน์ง่ายๆดังนี้:

>>> item_list = ['item', 5, 'foo', 3.14, True]
>>> item_list = set(item_list) - {'item', 5}
>>> item_list
{True, 3.14, 'foo'}
>>> # you can cast it again in a list-from like so
>>> item_list = list(item_list)
>>> item_list
[True, 3.14, 'foo']

6
ไม่รักษาลำดับของวัตถุแม้ว่า
Astrid

และจะลบรายการที่ซ้ำกันซึ่งอาจมีอยู่ในรายการ
kyriakosSt

1

ฉันกำลังโพสต์คำตอบของฉันใหม่จากที่นี่เพราะฉันเห็นว่ามันเหมาะกับที่นี่ อนุญาตให้ลบค่าหลายค่าหรือลบเฉพาะค่าที่ซ้ำกันของค่าเหล่านี้และส่งคืนรายการใหม่หรือแก้ไขรายการที่กำหนดแทน


def removed(items, original_list, only_duplicates=False, inplace=False):
    """By default removes given items from original_list and returns
    a new list. Optionally only removes duplicates of `items` or modifies
    given list in place.
    """
    if not hasattr(items, '__iter__') or isinstance(items, str):
        items = [items]

    if only_duplicates:
        result = []
        for item in original_list:
            if item not in items or item not in result:
                result.append(item)
    else:
        result = [item for item in original_list if item not in items]

    if inplace:
        original_list[:] = result
    else:
        return result

ส่วนขยาย Docstring:

"""
Examples:
---------

    >>>li1 = [1, 2, 3, 4, 4, 5, 5]
    >>>removed(4, li1)
       [1, 2, 3, 5, 5]
    >>>removed((4,5), li1)
       [1, 2, 3]
    >>>removed((4,5), li1, only_duplicates=True)
       [1, 2, 3, 4, 5]

    # remove all duplicates by passing original_list also to `items`.:
    >>>removed(li1, li1, only_duplicates=True)
      [1, 2, 3, 4, 5]

    # inplace:
    >>>removed((4,5), li1, only_duplicates=True, inplace=True)
    >>>li1
        [1, 2, 3, 4, 5]

    >>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
    >>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
    >>>li2
        ['abc', 'def', 'ghi']
"""

คุณควรมีความชัดเจนเกี่ยวกับสิ่งที่คุณต้องการทำแก้ไขรายการที่มีอยู่หรือสร้างรายการใหม่โดยมีบางรายการขาดหายไป สิ่งสำคัญคือต้องสร้างความแตกต่างนั้นในกรณีที่คุณมีข้อมูลอ้างอิงที่สองที่ชี้ไปยังรายการที่มีอยู่ ถ้าคุณมีเช่น ...

li1 = [1, 2, 3, 4, 4, 5, 5]
li2 = li1
# then rebind li1 to the new list without the value 4
li1 = removed(4, li1)
# you end up with two separate lists where li2 is still pointing to the 
# original
li2
# [1, 2, 3, 4, 4, 5, 5]
li1
# [1, 2, 3, 5, 5]

นี่อาจเป็นพฤติกรรมที่คุณต้องการหรือไม่ก็ได้


1

คุณสามารถใช้ฟังก์ชันfilterfalseจากโมดูลitertools

ตัวอย่าง

import random
from itertools import filterfalse

random.seed(42)

data = [random.randrange(5) for _ in range(10)]
clean = [*filterfalse(lambda i: i == 0, data)]
print(f"Remove 0s\n{data=}\n{clean=}\n")


clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1s\n{data=}\n{clean=}")

เอาท์พุต:

Remove 0s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 1, 1, 1, 4, 4]

Remove 0s and 1s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 4, 4]

0

แต่ถ้าฉันไม่ทราบดัชนีของรายการที่ต้องการลบล่ะ?

ฉันไม่เข้าใจว่าทำไมคุณไม่ชอบ. ลบ แต่เพื่อให้ได้ดัชนีแรกที่สอดคล้องกับการใช้ค่า .index (ค่า):

ind=item_list.index('item')

จากนั้นลบค่าที่เกี่ยวข้อง:

del item_list.pop[ind]

.index (value) รับการเกิดขึ้นครั้งแรกของค่าและ. ลบ (ค่า) จะลบการเกิดครั้งแรกของค่า


พิจารณาใช้del item_list[ind]แทนpopถ้าคุณไม่ต้องการค่าผลลัพธ์
kojiro

-1

คุณสามารถใช้สิ่งนี้ -

สมมติว่าเรามีรายชื่อ l = [1,2,3,4,5]

เราต้องการลบสองรายการสุดท้ายในคำสั่งเดียว

del l[3:]

เรามีผลลัพธ์:

ล. = [1,2,3]

ง่าย ๆ เข้าไว้

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