I have the following variables:
a = [1, 2, 3]
b = "de" # <-- not a (usual) list !
c = 5 # <-- not a list !
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]
Now I want to concat all a, b, c, d, e
to one list:
[1, 2, 3, "de", 5, 4, 5, 23, 11, 5, "dg", "kuku"]
I have tried itertools.chain
but it didn't work. Please advise how can I make the concatenation?
CodePudding user response:
chain
works with iterables. What you mean is: concatenate these lists and raw values.
I see two steps:
def ensure_list(x):
if isinstance(x, list):
return x
return [x]
lists = map(ensure_list, (a, b, c, d, e))
concatenated = list(itertools.chain.from_iterable(lists))
CodePudding user response:
You could define a function that takes an arbitrary number of arguments and iteratively constructs a list out of them depending on their type like this:
a = [1, 2, 3]
b = "de" # <-- not a (usual) list !
c = 5 # <-- not a list !
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]
def concat(*args):
out = []
for arg in args:
if isinstance(arg, list):
out.extend(arg)
else:
out.append(arg)
return out
print(concat(a,b,c,d,e))
Outputs:
[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']
Alternatively you could map over the list of args, ensure they're all a list, then use itertools.chain
to combine the map object like this:
def concat(*args):
return list(itertools.chain(*map(lambda x : x if isinstance(x, list) else [x], args)))
print(concat(a,b,c,d,e))
Outputs:
[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']
And here's a much more opaque way of accomplishing the same thing just for fun in a list comprehension:
def concat(*args):
return [x
for arg in args
for x in (arg if isinstance(arg, list) else [arg])]
print(concat(a,b,c,d,e))
Outputs:
[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']
CodePudding user response:
You have to combine append()
and extend()
because one of your examples is not a list
(b
and c
) but a single integer.
#!/usr/bin/env python3
a = [1, 2, 3]
b = "de"
c = 5
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]
the_input = [a, b, c, d, e]
result = []
for element in the_input:
if isinstance(element, list):
result.extend(element)
else:
result.append(element)
print(result)
I am not aware of any chain like method to improve that example.
CodePudding user response:
If all of your variables are lists you can use
concat = [*a, *b, *c, *d, *e]
The "*" will 'unpack', the list.
EDIT:
if some variables aren't lists
concat = []
for variable in (a, b, c, d, e):
# check if the variable is iterable (is a list, set, dict, ...)
if __hasattr__(variable, "__iter__"):
concat.extend(variable)
else:
concat.append(variable)
CodePudding user response:
I wouldn't recommend this, but here's another way of doing it if you like list comprehensions or one-liners:
to_concat = [a, b, c]
concatenated_list = []
concatenated_list = [item for sublist in [[list_or_val] if not isinstance(list_or_val, list) else list_or_val for list_or_val in to_concat] for item in sublist]
Output with a, b, c = "de", [1, 2], ["dg", "kuku"]
:
In [6]: concatenated_list
Out[6]: ['de', 1, 2, 'dg', 'kuku']
How does it work?
This part:
[[list_or_val] if not isinstance(list_or_val, list) else list_or_val for list_or_val in to_concat]
of the list comprehension creates a new list by transforming non-list values (like a
in our case) into lists (so "de"
becomes ["de"]
). Let's call it list_of_lists
. We now want to flatten list_of_lists
to get our end result, and we can do so by the other part of the list comprehension:
[item for sublist in list_of_lists for item in sublist]
(More info here on the flattening if you're interested)
As I've said, I wouldn't recommend this solution. It's quite a mess to understand, and it probably has terrible performance, so it's not suited to larger workloads.