Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing an item from a list of lists based on each of the lists first element

Given:

a = [[1,2],[3,4],[5,6],[7,8]]
b = 3

I would like to remove an item of a that has b as it's first item. So in this case we would remove [3,4] to give:

a = [[1,2],[5,6],[7,8]]

My current code is:

if b in [i[0] for i in a]:
    pos = [i[0] for i in a].index(b)
       del a[pos]

This works but it is slow. What would a better way to do this be?

EDIT: I've not tested performance before so I may be doing this wrong but I get this:

def fun1():
    lst = [[x, 2*x] for x in range(1000000)]
    lst = [x for x in lst if x[0] != 500]
    return lst

def fun2():
    lst = [[x, 2*x] for x in range(1000000)]
    for i in reversed(range(len(lst))):
        if lst[i][0] == 500:
            del lst[i]
    return lst

cProfile.runctx('fun1()', None, locals())
        6 function calls in 0.460 seconds

cProfile.runctx('fun2()', None, locals())
        6 function calls in 0.502 seconds
like image 557
AndrewK Avatar asked Apr 05 '18 07:04

AndrewK


People also ask

How do you remove items from the front of a list in Python?

Del operator has similar working as pop() method to remove the elements from the lists in python. The del operator removes the element from the list at a specified index location but does not return the removed item, unlike the pop() method.

What method is used to remove a specific item from a list?

There are three ways in which you can Remove elements from List: Using the remove() method. Using the list object's pop() method. Using the del operator.

How do you remove an item from a list using its index?

There are two options to remove an element by its index in list. Using del statement, and using pop() method. The del statement needs index of the element to remove. The pop() method of built-in list class requires index as argument.


4 Answers

Reverse delete a, modifying it in-place:

for i in reversed(range(len(a))):
    if a[i][0] == 3:
        del a[i]

An in-place modification means that this is more efficient, since it does not create a new list (as a list comprehension would).


Since OP requests a performant solution, here's a timeit comparison between the two top voted answers here.

Setup -

a = np.random.choice(4, (100000, 2)).tolist()

print(a[:5])
[[2, 1], [2, 2], [3, 2], [3, 3], [3, 1]]

List comprehension -

%timeit [x for x in a if x[0] != b]
11.1 ms ± 685 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Reverse delete -

%%timeit
for i in reversed(range(len(a))):
    if a[i][0] == 3:
        del a[i]

10.1 ms ± 146 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

They're really close, but reverse delete has a 1UP on performance because it doesn't have to generate a new list in memory, as the list comprehension would.

like image 89
cs95 Avatar answered Oct 17 '22 01:10

cs95


You can use a list comprehension:

>>> a = [[1,2],[3,4],[5,6],[7,8]]
>>> b = 3
>>> a = [x for x in a if x[0] != b]
>>> a
[[1, 2], [5, 6], [7, 8]]
like image 26
Keyur Potdar Avatar answered Oct 17 '22 01:10

Keyur Potdar


for i in a[:-1]:
    if i[0]==b:
        a.remove(i)

What about this?

The output is

[[1, 2], [5, 6], [7, 8]]

like image 29
Pabasara Ranathunga Avatar answered Oct 17 '22 01:10

Pabasara Ranathunga


If your list are small then you are also try filter ,

a = [[1,2],[3,4],[5,6],[7,8]]
b = 3

print(list(filter(lambda x:x[0]!=b,a)))

output:

[[1, 2], [5, 6], [7, 8]]
like image 23
Aaditya Ura Avatar answered Oct 17 '22 01:10

Aaditya Ura