Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected output from list comprehension

I have an input list as follows:

test_list = ['a', ('abc', 'd'), ['efgh', 'i'], 'jkl']

which I need to flatten, so getting rid of the tuple and list as respective second and third element of test_list

Expected output:

['a', 'abc', 'd', 'efgh', 'i', 'jkl']

I have a problem finding the correct list comprehension for this. I have tried the following 2 examples:

result = [xs if type(xs) is str else x for xs in test_list for x in xs]
print('result', result) 
# this outputs:
# ['a', 'abc', 'd', 'efgh', 'i', 'jkl', 'jkl', 'jkl']

result = [x if ((type(xs) is list) or (type(xs) is tuple)) else xs for xs in test_list for x in xs]
print('result',result)
#this also outputs:
# ['a', 'abc', 'd', 'efgh', 'i', 'jkl', 'jkl', 'jkl']  

as you can see, it does "flatten" the list, but it repeats the last element based on the number of characters in the last element. Example if the last element of the test_list is 'jklm' then the in the result the last element is repeated 4 times.

I would like to know if there is a list comprehension which flatten my input list to the expected output without repeating the last element.

like image 350
Edwin van Mierlo Avatar asked Dec 10 '22 08:12

Edwin van Mierlo


2 Answers

The following nested comprehension will work:

[x for sub in test_list for x in (sub if isinstance(sub, (list, tuple)) else [sub])]

This uses isinstance which should preferred over type(...) and can be given multiple types. If any top level element is not a list or tuple, it is wrapped in a list.

like image 95
user2390182 Avatar answered Dec 12 '22 20:12

user2390182


You can try:

test_list = ['a', ('abc', 'd'), ['efgh', 'i'], 'jkl']
result = [x for xs in test_list for x in (xs if isinstance(xs, (tuple, list)) else [xs])]

But I wouldn't use this, I would just write a for loop

like image 45
juanpa.arrivillaga Avatar answered Dec 12 '22 21:12

juanpa.arrivillaga