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
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.