วิธีลบองค์ประกอบเฉพาะออกจากอาร์เรย์โดยใช้ python


142

ฉันต้องการเขียนสิ่งที่ลบองค์ประกอบเฉพาะออกจากอาร์เรย์ ฉันรู้ว่าฉันต้องforวนรอบอาร์เรย์เพื่อค้นหาองค์ประกอบที่ตรงกับเนื้อหา

สมมติว่าฉันมีอีเมลจำนวนมากและต้องการกำจัดองค์ประกอบที่ตรงกับสตริงอีเมลบางส่วน

ฉันต้องการใช้โครงสร้างสำหรับลูปเพราะฉันต้องใช้ดัชนีเดียวกันสำหรับอาร์เรย์อื่นด้วย

นี่คือรหัสที่ฉันมี:

for index, item in emails:
    if emails[index] == 'something@something.com':
         emails.pop(index)
         otherarray.pop(index)

7
คุณกำลังมองหาlist.remove(x)?
Jacob

ไม่มาก ฉันต้องการใช้ for loop เพื่อให้สามารถนำดัชนีกลับมาใช้ใหม่ได้
locoboy

4
คุณไม่ควรเปลี่ยนรายการในขณะที่ทำซ้ำ
Jacob

ทำไมฉันไม่ควรทำเช่นนี้ ยังไม่ได้ผลสำหรับฉัน
locoboy

คำตอบ:


205

คุณไม่จำเป็นต้องวนซ้ำอาร์เรย์ แค่:

>>> x = ['ala@ala.com', 'bala@bala.com']
>>> x
['ala@ala.com', 'bala@bala.com']
>>> x.remove('ala@ala.com')
>>> x
['bala@bala.com']

การดำเนินการนี้จะลบเหตุการณ์แรกที่ตรงกับสตริง

แก้ไข: หลังจากแก้ไขแล้วคุณยังไม่จำเป็นต้องทำซ้ำอีก แค่ทำ:

index = initial_list.index(item1)
del initial_list[index]
del other_list[index]

1
ดูด้านบนฉันต้องการใช้ for loop เพื่อนำดัชนีเดิมกลับมาใช้ใหม่
locoboy

แก้ไขคำตอบของฉัน ยังไม่จำเป็นต้องวนซ้ำ
Bogdan

1
คุณจะตรวจสอบก่อนได้อย่างไรว่ามีรายการอยู่ใน initial_list อาจมีบางกรณีที่ไม่มีอยู่จริงและคุณจะไม่ต้องลบออก
locoboy

18

การใช้filter()และlambdaจะให้วิธีการลบค่าที่ไม่ต้องการ:

newEmails = list(filter(lambda x : x != 'something@something.com', emails))

สิ่งนี้ไม่ได้แก้ไขอีเมล สร้างรายการใหม่ newEmails ที่มีเฉพาะองค์ประกอบที่ฟังก์ชัน anonymous ส่งคืน True


5

สำหรับลูปของคุณไม่ถูกต้องหากคุณต้องการดัชนีในการใช้สำหรับลูป:

for index, item in enumerate(emails):
    # whatever (but you can't remove element while iterating)

ในกรณีของคุณโซลูชัน Bogdan ก็ใช้ได้ แต่ตัวเลือกโครงสร้างข้อมูลของคุณไม่ค่อยดีนัก การต้องรักษาสองรายการนี้ด้วยข้อมูลจากรายการหนึ่งที่เกี่ยวข้องกับข้อมูลจากอีกรายการหนึ่งในดัชนีเดียวกันนั้นเป็นเรื่องที่ไม่สะดวก

รายการ tupple (อีเมลข้อมูลอื่น ๆ ) อาจจะดีกว่าหรือใช้คำสั่งที่มีอีเมลเป็นคีย์


4

วิธีที่ดีในการทำเช่นนี้คือการใช้zip()และนิพจน์ List Compiltyion / Generator:

filtered = (
    (email, other) 
        for email, other in zip(emails, other_list) 
            if email == 'something@something.com')

new_emails, new_other_list = zip(*filtered)

นอกจากนี้หากคุณไม่ได้ใช้array.array()หรือnumpy.array()เป็นไปได้มากว่าคุณกำลังใช้[]หรือlist()ซึ่งให้ Lists ไม่ใช่ Arrays ไม่ใช่สิ่งเดียวกัน.


1
ไม่แน่ใจว่าสิ่งนี้ "มีสติ" อย่างไรเมื่อเทียบกับคำตอบของ @ Bogdan ซึ่งสะอาดกว่ามาก
Jordan Lapp

ขอขอบคุณที่ชี้ให้เห็นว่าอาร์เรย์ไม่เหมือนกับรายการ คำตอบที่เลือกใช้ไม่ได้กับอาร์เรย์ใน 2.7
EL_DON

2

มีทางเลือกอื่นสำหรับปัญหานี้ซึ่งเกี่ยวข้องกับการจับคู่ที่ซ้ำกัน

เราเริ่มต้นด้วย 2 รายการที่มีความยาวเท่ากัน: emails, otherarray. วัตถุประสงค์คือการลบรายการจากทั้งสองรายการสำหรับแต่ละดัชนีiที่emails[i] == 'something@something.com'ที่

สิ่งนี้สามารถทำได้โดยใช้การทำความเข้าใจรายการแล้วแยกผ่านzip:

emails = ['abc@def.com', 'something@something.com', 'ghi@jkl.com']
otherarray = ['some', 'other', 'details']

from operator import itemgetter

res = [(i, j) for i, j in zip(emails, otherarray) if i!= 'something@something.com']
emails, otherarray = map(list, map(itemgetter(0, 1), zip(*res)))

print(emails)      # ['abc@def.com', 'ghi@jkl.com']
print(otherarray)  # ['some', 'details']

0

หากคุณต้องการลบดัชนีของอาร์เรย์:

ใช้ array_name.pop (index_no.)

เช่น: -

>>> arr = [1,2,3,4]
>>> arr.pop(2)
>>>arr
[1,2,4]

หากคุณต้องการลบสตริง / องค์ประกอบเฉพาะจากอาร์เรย์แล้ว

>>> arr1 = ['python3.6' , 'python2' ,'python3']
>>> arr1.remove('python2')
>>> arr1
['python3.6','python3']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.