Consider the list:
list_1 = [
[
[1, 2, 3], [], [3, 4, 5], [], [4, 5, 6], [7, 8, 9], [9, 1, 0]
],
[
[0, 1, 2], [9, 0, 1], [], [0, 1, 3], [1, 1, 1], [9, 5, 6], [3, 6, 7]
],
[
[1, 2, 4], [4, 5, 6], [], [1, 0, 1], [0, 1, 1], [3, 9, 7], []
],
[
[1, 3, 4], [], [3, 5, 6], [], [], [], [0, 7, 0]
]
]
I want to remove a row if it contains empty list either at 1st , 3rd or 7th position.
For example above the 2nd and 3rd rows must be removed. I tried this:
list_2 = [sublist for sublist in list_1 if all(x for x in sublist)]
How I call the index 1, 3, 7 in this?
CodePudding user response:
Using filter
and list slicing with operator.itemgetter
.
NB. as your lists have 7 elements and python indexing starts at 0, I assumed you mean elements 0, 2, 6
from operator import itemgetter
list_2 = list(filter(lambda l: [] not in itemgetter(0,2,6)(l), list_1))
output:
[[[1, 2, 3], [], [3, 4, 5], [], [4, 5, 6], [7, 8, 9], [9, 1, 0]],
[[1, 3, 4], [], [3, 5, 6], [], [], [], [0, 7, 0]]]
CodePudding user response:
This should work.
Method 1
The outer loop loops over the elements ('row's) of list_2
whereas the inner loop, for some fixed element of list_2
loops over the elements of that element of list_2
until it finds an empty list in the required position and then breaks from the inner loop so that we move onto another element ('row') of list_2
. Before the break, the list_2
index that is in place is stored in the delete_indices
list. After the loop is done, we use delete_indices
to decide which rows to keep.
indices = (0, 2, 6)
delete_indices = []
for idx_x, x in enumerate(list_1):
for idx_y, y in enumerate(x):
if idx_y in indices and not y:
delete_indices.append(idx_x)
break
list_2 = [x for idx, x in enumerate(list_1) if idx not in delete_indices]
Output
[[[1, 2, 3], [], [3, 4, 5], [], [4, 5, 6], [7, 8, 9], [9, 1, 0]],
[[1, 3, 4], [], [3, 5, 6], [], [], [], [0, 7, 0]]]
Method 2 follows a similar logic to method 1 and is faster than method 1 (see below).
def pred(l: list, indices = (0, 2, 6)):
for idx, item in enumerate(l):
if not item and idx in indices:
return True
return False
list_2 = [item for item in list_1 if not pred(item)]
Comparison
Efficiency-wise, you should prefer @mozway's way.
# mozway's way (no rhymes intended)
908 ns ± 2.87 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# Method 2
1.4 µs ± 2.53 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# Method 1
1.78 µs ± 20.5 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)