Simple, just pop on the list item.
>>> a = [[1,2,3,4], [6,7,8,9]]
>>> a[1].pop(3)
>>> a
[[1, 2, 3, 4], [6, 7, 8]]
Answer from nathancahill on Stack OverflowSimple, just pop on the list item.
>>> a = [[1,2,3,4], [6,7,8,9]]
>>> a[1].pop(3)
>>> a
[[1, 2, 3, 4], [6, 7, 8]]
You should use del to remove an item at a specific index:
>>> a = [[1,2,3,4], [6,7,8,9]]
>>> del a[1][3]
>>> a
[[1, 2, 3, 4], [6, 7, 8]]
>>>
list.pop should only be used when you need to save the value you just removed.
Doing an assignment for class where I have to search through a 2d array for an element in a list and then delete its sublist. What would be the best way to go about this to avoid index out of bounds exceptions? Thanks!
Imagine you have this list:
l = [[1,0,0], [0,4,0], [0,0,1], [3,0,0]]
You can delete (say) the 1's using a list comprehension instead:
l = [[0 if x == 1 else x for x in sub_l] for sub_l in l]
[[0, 0, 0], [0, 4, 0], [0, 0, 0], [3, 0, 0]]
I think without this line your code would execute in less time.
if int_to_delete in i:
Because the membership function (in) will be basically compare every element in list and if the given number is member then again you are performing check in the following for loop.
You are using a data structure that supports only linear lookup. You can use the bisect module to do logarithmic-time lookup (deletion will still be linear time), but why bother when there is a structure that lets you do constant-time lookup and deletion?
Use a dictionary:
people = dict(people)
Now removal is trivial:
for name in people_rem:
del people[name]
Notice that this runs in O(len(people_rem)) time, not O(len(people)). Since presumably len(people_rem) < len(people_rem), this is a good thing (TM). I'm not counting the O(len(people)) conversion to a dictionary, since you can likely do that directly when you create people in the first place, making it no more expensive than building the initial list.
Have you tried doing it through pandas? Check if this is faster.
import pandas as pd
people = [['Amy', 25], ['Bella', 30], ['Charlie', 29], ['Dean', 21], ['Elliot', 19]]
people_rem = ['Amy', 'Charlie', 'Dean']
def remove(people, people_rem):
df = pd.DataFrame(people, columns = ['Name', 'Age'])
for person in people_rem:
df.drop(df[df.Name == person].index, inplace=True)
return df.values.tolist()
final_people = remove(people, people_rem)
print(final_people)
Let's say I have the following:
array = [[20 , 'apples' , 1] , [25 , 'pears' , 3] , [50 , 'grapes' , 100] , [9 , 'apples' , 99]]
I'm trying to remove the duplicates when the second item matches... in this case "apples" so and updated array would look like the following (keeping the first instance and removing the rest:
[20 , 'apples' , 1]
['25' , 'pears' , 3]
['50' , 'grapes' , '100']
I've looked around but all I'm finding is information for deleting duplicates from 1 dimensional lists but can't seem to find anything for multidimensional lists based on what I'm needing to match/remove.
My actual code has several thousand entries like this and the single item duplicates are causing issues with some sorting/ranking reporting I am trying to generate.
Any suggestions or recommendations would be much appreciated. Thank you
Just for the sake of showing a much simpler way of doing this using list comprehensions, the sorted method and slicing:
d = [[1, 3, 4], [2, 4, 4], [3, 4, 5]]
n = [sorted(l)[1:-1] for l in d]
print(n)
# [[3], [4], [4]]
Some reading material on each of the items used to solve this problem:
- list comprehension
- sorted
- slicing
To take care of duplicates, this answer by Padraic is very well done.
If you want to remove all occurrences, you will have to find the min and max and remove all occurrence from each sublist:
def remove(l):
for sub in l:
t = {min(sub), max(sub)}
sub[:] = (ele for ele in sub if ele not in t)
l = [[1, 3, 4], [1, 2, 4, 4], [3, 4, 5]]
remove(l)
Which will give you:
[[3], [2], [4]]
To find the min and max in a single pass you can use a helper function:
def min_max(sub):
# all numbers are > float("-inf") and < float("inf")
mx, mn = float("-inf"), float("inf")
for ele in sub:
if ele < mn:
mn = ele
if ele > mx:
mx = ele
return {mn, mx}
def remove(l):
for sub in l:
# find min and max
mn_mx = min_max(sub)
# update sublist so all occurrences of either are removed
sub[:] = (ele for ele in sub if ele not in mn_mx)
Even if your own logic worked and you wanted to remove all the elements equal to the max, it would not work using remove as it will only remove the first occurrence each time.
In [8]: l = [1,2,3,4,4]
In [9]: l.remove(4)
In [10]: l
Out[10]: [1, 2, 3, 4]
Based on one of your comments you seem to have strings in your sublists which will error when compared to an int, if the string is always the first element you can slice it off:
from itertools import islice
def remove(l):
for sub in l:
sub = sub[1:]
mn_mx = min_max(sub)
sub[:] = (ele for ele in sub if ele not in mn_mx)
Use np.isin:
mask = np.isin(actions[0], keys, invert=True)
result = actions[:, mask]
The following will filter out columns of actions that have a first row entry in the set keys:
import numpy as np
x = 10
actions = np.random.randint(5, size=(2,x))
print(actions)
keys = np.array([1,2,3])
print(keys)
filtered_actions = actions[:,~np.sum([actions[0,:] == key for key in keys], dtype=bool, axis=0)]
print(filtered_actions)