155

I want to write something that removes a specific element from an array. I know that I have to for loop through the array to find the element that matches the content.

Let's say that I have an array of emails and I want to get rid of the element that matches some email string.

I'd actually like to use the for loop structure because I need to use the same index for other arrays as well.

Here is the code that I have:

for index, item in emails:
    if emails[index] == 'something@something.com':
         emails.pop(index)
         otherarray.pop(index)
Gort the Robot
  • 2,329
  • 16
  • 21
locoboy
  • 38,002
  • 70
  • 184
  • 260
  • 7
    Are you looking for [`list.remove(x)`](http://docs.python.org/tutorial/datastructures.html#more-on-lists)? – Jacob Aug 19 '11 at 07:28
  • not quite. i would like to use the for loop so that i can reuse the index – locoboy Aug 19 '11 at 07:35
  • 4
    You shouldn't change the list while iterating over it. – Jacob Aug 19 '11 at 07:43
  • why shouldn't i do this? also it's not working for me. – locoboy Aug 19 '11 at 07:53
  • 6
    Have alook at this: [Thou Shalt Not Modify A List During Iteration](http://unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/) – Jacob Aug 19 '11 at 07:59
  • @cularis I prefer Bogdan's answer, but is it okay to modify a list once if you then break out (of the for loop)? – bdeniker Aug 19 '11 at 08:38
  • You can also iterate over the list in reverse order. The removed element index will then refer to the last element examined, but when the index is decremented, it will point to the next one you wish to examine. I don't believe that this behavior is supported, but works well enough in the versions to date so as to be useful. – MrWonderful Jan 02 '15 at 12:09

7 Answers7

227

You don't need to iterate the array. Just:

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

This will remove the first occurence that matches the string.

EDIT: After your edit, you still don't need to iterate over. Just do:

index = initial_list.index(item1)
del initial_list[index]
del other_list[index]
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Bogdan
  • 8,017
  • 6
  • 48
  • 64
21

Using filter() and lambda would provide a neat and terse method of removing unwanted values:

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

This does not modify emails. It creates the new list newEmails containing only elements for which the anonymous function returned True.

Tobias
  • 4,523
  • 2
  • 20
  • 40
Ron Kalian
  • 3,280
  • 3
  • 15
  • 23
5

Your for loop is not right, if you need the index in the for loop use:

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

In your case, Bogdan solution is ok, but your data structure choice is not so good. Having to maintain these two lists with data from one related to data from the other at same index is clumsy.

A list of tupple (email, otherdata) may be better, or a dict with email as key.

MatthieuW
  • 2,292
  • 15
  • 25
4

The sane way to do this is to use zip() and a List Comprehension / Generator Expression:

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

new_emails, new_other_list = zip(*filtered)

Also, if your'e not using array.array() or numpy.array(), then most likely you are using [] or list(), which give you Lists, not Arrays. Not the same thing.

pillmuncher
  • 10,094
  • 2
  • 35
  • 33
3

There is an alternative solution to this problem which also deals with duplicate matches.

We start with 2 lists of equal length: emails, otherarray. The objective is to remove items from both lists for each index i where emails[i] == 'something@something.com'.

This can be achieved using a list comprehension and then splitting via 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']
jpp
  • 159,742
  • 34
  • 281
  • 339
3

If you want to delete the index of array:

Use array_name.pop(index_no.)

ex:-

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

If you want to delete a particular string/element from the array then

>>> arr1 = ['python3.6' , 'python2' ,'python3']
>>> arr1.remove('python2')
>>> arr1
['python3.6','python3']
0

Use setdiff1d() from numpy to remove desired items from an array. You can pass an array of elements to be removed from the given array.

import numpy as np
test=np.array([1,2,3,4,5,45,65,34])
elements_to_remove=np.array([2,65])
t=np.setdiff1d(test,elements_to_remove)
print(test)
print(t)

The output looks like this:

[ 1  2  3  4  5 45 65 34]
[ 1  3  4  5 34 45]

2 and 65 has been removed from the original array.

Binod
  • 397
  • 4
  • 5