How to convert a nested list of strings to a one list?

890 Views Asked by At

I wanted to convert a nested list of strings into a single list. For example, if there is a list like,

fruits = ['apple','orange, ['pineapple','grapes']]

I want to convert this to:

fruits = ['apple','orange','pineapple','grapes']

I tried using the more_itertools.chain.from_iterable(fruits) but the output I am getting is:

['a','p','p','l','e','o','r','a','n','g','e','pineapple','grapes']

Even tried [inner for item in fruits for inner in item], this also gves the same output as above.

I also tried [inner for item in fruits for inner in ast.literal_eval(item)] but this was giving an error ValueError: malformed string

Is there a workaround? Thanks in advance.

6

There are 6 best solutions below

0
On BEST ANSWER

If you're using the more_itertools module try the collapse function:

print(list(more_itertools.collapse(fruits)))

Output:

['apple', 'orange', 'pineapple', 'grapes']
0
On

Every one here has already given some great answers, but the most pythonic way would be to use regex. We can either remove the square brackets or extract only the alphabets

import re
fruits = ['apple','orange', ['pineapple','grapes'],['Mango',"Guava","banana"],'Fruits']
fruits = str(fruits)
pattern1 = "[A-Za-z]+"
res1 = re.findall(pattern1,fruits)
print(res1)

Python 3.9.4 output:

['apple', 'orange', 'pineapple', 'grapes', 'Mango', 'Guava', 'banana', 'Fruits']
2
On

see below (assuming fruits contains strings or lists only)

fruits = ['apple', 'orange', ['pineapple', 'grapes']]
flat = []
for f in fruits:
    if isinstance(f, str):
        flat.append(f)
    else:
        flat.extend(f)
print(flat)

output

['apple', 'orange', 'pineapple', 'grapes']
0
On

Try:

fruits = ["apple", "orange", ["pineapple", "grapes"]]
fruits = [l for v in fruits for l in (v if isinstance(v, list) else [v])]
print(fruits)

Prints:

['apple', 'orange', 'pineapple', 'grapes']
0
On

What you are looking for is collapse method from the same package.

Here's an example usage:

import more_itertools

fruits = ['apple','orange', ['pineapple','grapes']]
print(list(more_itertools.collapse(fruits, base_type=str)))
# ['apple', 'orange', 'pineapple', 'grapes']
0
On

There's arbitrarily elegant methods and libraries you can use, but honestly, classical use case for recursion:

def to_list_of_strings(thing):
  if type(thing) is str:
    return [thing]
  # it's not just a string, so take apart
  retlist = []
  for element in thing:
    retlist += to_list_of_strings(element)
  return retlist

Note that this works on arbitrary deeply nested lists like

[[ 
  "a",
 [ 
   "more",
   [ 
     "than"
   ],
   "just",
   [
     [
       "a",
       "single",
       [
         "layer"
       ]
     ],
     "deep"
   ],
   "list"
  ]
]]

a lot of the other answers don't.

This is, by the way, a depth-first search algorithm.