0

I've written a code that had to unpack lists, I mean turn

[None, [1, ({2, 3}, {'foo': 'bar'})]]

into

[None, 1, 2, 3, 'foo', 'bar']

Actually, this is my solution:

    import re
def unpack(l):
    pattern = r"\w+"
    fin = []
    for i in l:
        match = re.findall(pattern, i)
        fin.append(match)
    return fin

but it causes problem TypeError: expected string or buffer and, yes, I've looked through other similar questions. Please tell me how to do it correctly

and regex chooses accurately what I need enter image description here

Lewis
  • 43
  • 1
  • 5

1 Answers1

3

You can not apply a regular expression to a list. You could turn the list into a string using str, and then apply the regex, but you probably should not.*)

Intead, I suggest a recursive function for flattening the list, and also iterating both the keys and values in any nested dictionaries, and applying itself recursively to any nested lists, sets, tuples or dicts.

def unpack(seq):
    if isinstance(seq, (list, tuple, set)):
        yield from (x for y in seq for x in unpack(y))
    elif isinstance(seq, dict):
        yield from (x for item in seq.items() for y in item for x in unpack(y))
    else:
        yield seq

lst = [None, [1, ({2, 3}, {'foo': 'bar'})]]
print(list(unpack(lst)))
# [None, 1, 2, 3, 'foo', 'bar']

Update: For Python 2.x, replace the yield from (...) with for x in (...): yield x, or directly return lists instead of using a generator to yield elements:

def unpack(seq):
    if isinstance(seq, (list, tuple, set)):
        return [x for y in seq for x in unpack(y)]
    elif isinstance(seq, dict):
        return [x for item in seq.items() for y in item for x in unpack(y)]
    else:
        return [seq]

*) Since you asked: what if the numbers contain a dot, or the strings contain... well, anything? Also, you'd have to recreate the actual objects with their proper type (like int) from the matched strings. And what if the list contains objects other than strings or numbers, that can not easily be recreated from their string representation?

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • @Lewis Did not see the Python 2 tag, let me fix that... done. – tobias_k Jul 13 '18 at 09:58
  • thanks, it works! and why _"You could turn the list into a string using str, and then apply the regex, but you probably should not."_ – Lewis Jul 13 '18 at 10:09
  • @Lewis Well, what if the numbers contain a dot, or the strings contain... well, anything? Also, you'd have to recreate the actual objects with their proper type from the matched strings. And what if the list contains objects other than strings or numbers, that can not easily be recreated from their string representation? – tobias_k Jul 13 '18 at 10:15
  • Wooow, such a headache. Yes, your answer is much better, thanks – Lewis Jul 13 '18 at 10:20