简体   繁体   中英

Remove an element at a specific position from every sublist

I have a list such as:

a = [[1,'b',2],[3,':',4],[5,':',6]]

I want to remove the 'b' and ':' characters so that I end up with:

[[1,2],[3,4],[5,6]]

(Note that the fact that these characters are in the second position of each sublist is just an accident of my choice of example - the real data set I am working on has the same characters in random positions).

I have chosen to use a list comprehension to do this. Here is an example of the code to iterate over each item of the sublists:

for list in a:
    for number in list:
        print number

But when I implement my list comprehension instead of the print statement like this:

b = []

for list in a:
    for number in list:
        b = [number for number in list if number != 'b' and number != ':']
        print b

I get the following output:

[1, 2]
[1, 2]
[1, 2]
[3, 4]
[3, 4]
[3, 4]
[5, 6]
[5, 6]
[5, 6]

My question is, why are there three copies of each sublist? I was expecting

[1,2]
[3,4]
[5,6]

Any help and/or guidance would be much appreciated.

Cheers.

If all you're trying to remove is b and : , you can use a nested list comprehension with a set membership test:

a_new = [[y for y in x if y not in {'b', ':'}] for x in a]

Although, if you'd like to generalise this to remove any non-numeric element, filter with an isinstance check:

import numbers
a_new = [[y for y in x if isinstance(y, numbers.Number)] for x in a]

Note that this is the same as:

a_new = []
for i in a:
    a_new.append([])
    for j in i:
        if isinstance(j, numbers.Number):
            a_new[-1].append(j)

Note that you only need 2 loops here (your code has 3 which is why everything is replicated 3 times - the number of items in each inner list!).

print(a_new)
[[1, 2], [3, 4], [5, 6]]

Another note here, numbers.Number is an injected superclass of any numeric value (including irrational values). If your use case does not include complex numbers, you may instead want to use numbers.Rational or numbers.Real .

Final note, as mentioned here , please don't use list / dict other such names as variables, they end up shadowing the actual builtins.

try this

d=[[number2 for number2 in number if number2 != 'b' and number2 != ':'] for number in a ]

output:

[[1, 2], [3, 4], [5, 6]]

This seems like an XY problem . Below are some options, depending on what you are really looking to do.

Only include numeric types and return list

arr = [[1,'b',2], [3,':',4], [5,':',6]]

def is_num(x):
    return isinstance(x, (int, float))

arr = [[i for i in k if is_num(i)] for k in arr]

# [[1, 2], [3, 4], [5, 6]]

Only exclude 'b' and ':' characters and return list

See @Coldspeed's solution.

I'd do list comprehension aswell but here is a variant with del .

lst = [[1,'b',2],[3,':',4],[5,':',6]]

for x in lst:
    for idx, y in enumerate(x):
        if y in {'b', ':'}:
            del x[idx]
            break

Of course this only works if there is only one special character. Otherwise you'd need to iterate over the sublists backwards.

Just create more functions to make everything more readable:

INVALID_ENTRIES = {':', 'b'}

def is_relevant_entry(entry):
    return entry not in INVALID_ENTRIES

def clean_item(item):
    return list(filter(is_relevant_entry, item))

def clean_list(lst):
    return list(map(clean_item, lst))

a = [[1,'b',2],[3,':',4],[5,':',6]]
result = clean_list(a)

I think it is much better than these comprehension one-liners.

No loops, names convey the meaning and usage of the standard library :)

In python2 map and filter are eager so you don't need to wrap with list

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