简体   繁体   中英

Remove sublist from nested list (finding index of the sublist)

I have a nested list like this:

lists = [[['L', 5], ['B', 20], ['A', 10]], 
        [['B', 200], ['J', 90]], 
        [['L', 5], ['L', 6]], 
        [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

How can I remove sublists that have string which is not A,B,L(remove the whole sublist not only the list that not A,B,L) How can I find the index of sublist that invalid items belong to (in this case is 1)(need the index for further task)

This is what I have tried, it can find invalid item but I do not know to find index of the sublist

for j in range (len(lists)):
    for i in range (len(lists[j])):
        if lists[j][i][0] != 'L' and lists[j][i][0] != 'A' and lists[j][i][0] != 'B':
            return False
return True 

I want the result to be like this:

lists = [[['L', 5], ['B', 20], ['A', 10]],  
        [['L', 5], ['L', 6]], 
        [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

You can efficiently modify lists inplace using the reverse-delete idiom:

keep = ('A', 'B', 'L')
for i in reversed(range(len(lists))):
    if any(l[0] not in keep for l in lists[i]):  
        del lists[i]

print(lists)
# [[['L', 5], ['B', 20], ['A', 10]],
#  [['L', 5], ['L', 6]],
#  [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

any returns True if any of the sublists' first element is not in keep .


Alternatively, you can create a new list with a list comprehension:

[l for l in lists if not any(l_[0] not in keep for l_ in l)]
# [[['L', 5], ['B', 20], ['A', 10]],
#  [['L', 5], ['L', 6]],
#  [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

As @coldspeed suggests, using a set to check if the letters exists allows optimal O(1) lookups.

If you don't want to use any builtin functions like any() , first make a function that checks if the first letter of each sublists inner list exists:

valid = {"A", "B", "L"}

def check_valid(sublst):
    for fst, *_ in sublst: 
        if fst not in valid:
            return False
    return True

Or without tuple unpacking if you prefer:

def check_valid(sublst):
    for lst in sublst:
        if lst[0] not in valid:
            return False
    return True

Then you can reconstruct a new list with the incorrect lists filtered out:

result = []
for sublst in lists:
    if check_valid(sublst):
        result.append(sublst)

print(result)
# [[['L', 5], ['B', 20], ['A', 10]], [['L', 5], ['L', 6]], [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

Or as a list comprehension:

result = [sublst for sublst in lists if check_valid(sublst)]
print(result)
# [[['L', 5], ['B', 20], ['A', 10]], [['L', 5], ['L', 6]], [['A', 10], ['L', 12], ['A', 11], ['A', 15]]]

Note: It is always better to use builtin functions for convenience, since it saves you having to reinvent the wheel and usually leads to shorter, more concise code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM