简体   繁体   中英

Removing all elements of a particular class from a list of lists

I'm in the process of becoming familiar with Python and I'm looking at basic manipulation of "lists" currently.

So here's my problem.

I have a list of lists which contains mostly "string" class elements aside from two integers: Suppose I want to remove only the integer class element so I'm left with an otherwise unaltered list of lists containing only the string elements:

ie My original list is the following:

    listoflists=[['Juice', 'Pizza', 'Potatoes', 'Bananas', 5, 10],
 ['eggs', 'ham', 'chicken', 'Pineapple'],
 'Onions']

and I want this to become the following:

listoflist=[['Juice', 'Pizza', 'Potatoes', 'Bananas'],
 ['eggs', 'ham', 'chicken', 'Pineapple'],
 'Onions']

Thus far I've found out how to remove integer class element from a singular list with the following:

 no_integer_list = [x for x in listA if not isinstance(x, int)]

But I'm struggling to get my head around how to apply this to a list of lists.

I was thinking of making a for loop to read each list within the multilist and apply the above code to each, but I'm not sure how to do this.

Any help with this will be much appreciated. Many thanks in advance.

Assuming that you only have one level of sublists (and your last element is a list and not a string), you could use a nested list comprehension like so

filtered = [[x for x in sublist if not isinstance(x, int)] for sublist in listoflists]

Outputs :

[['Juice', 'Pizza', 'Potatoes', 'Bananas'], ['eggs', 'ham', 'chicken', 'Pineapple'], ['Onions']]

If your last element is intentionally a string (or could possibly be an int ), I would scrap the messy one liners and just write a simple function like so

def filter_list(listoflists):
    newlist = []
    for element in listoflists:
        if isinstance(element, list):
            newlist.append([x for x in element if not isinstance(x, int)])
        elif isinstance(element, int):
            continue
        else:
            newlist.append(element)
    return newlist

Note that this is designed to simply remove all int types- other types will remain. If you want to only retain strings and discard all other types, you could use stop using the negation and have

def filter_list(listoflists):
    newlist = []
    for element in listoflists:
        if isinstance(element, list):
            newlist.append([x for x in element if isinstance(x, str)])
        elif isinstance(element, str):
            newlist.append(element)
    return newlist 
>>> [[i for i in item if not isinstance(i, int)] if isinstance(item, list) else item for item in listoflists]
[['Juice', 'Pizza', 'Potatoes', 'Bananas'],
 ['eggs', 'ham', 'chicken', 'Pineapple'],
 'Onions']

UPDATE: just for completeness if you outer list also has integers and you want to remove those too:

[[i for i in item if not isinstance(i, int)] if isinstance(item, list) else item 
 for item in listoflists if not isinstance(item, int)]

You approach is completly fine, but you need to do it for every sublist by using the map() function or a list comprehension.

>>> l = [['Juice', 'Pizza', 'Potatoes', 'Bananas', 5, 10], ['eggs', 'ham', 'chicken', 'Pineapple'], 'Onions']
>>> map(lambda x: filter(lambda y: not isinstance(y,int),x),l)
[['Juice', 'Pizza', 'Potatoes', 'Bananas'], ['eggs', 'ham', 'chicken', 'Pineapple'], 'Onions']

Instead of using filter() and map(), you can also use the equivalent list comprehension method.

A flexible recursive solution for any number of nested levels (even varying depths) and for both lists and tuples (output will be list though):

eliminate_int = lambda l: [eliminate_int(x) if isinstance(x, list) or isinstance(x, tuple) \
                           else x for x in l if not isinstance(x, int)]

listoflists=[ ['Juice', 'Pizza', 'Potatoes', 'Bananas', 5, 10],
              ['eggs', 'ham', 'chicken', 'Pineapple'],
              'Onions' ]

print(eliminate_int(listoflists))

Output:

[['Juice', 'Pizza', 'Potatoes', 'Bananas'], ['eggs', 'ham', 'chicken', 'Pineapple'], 'Onions']

See this code running on ideone.com

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