delete items from list of list: pythonic way - python

I've this kind of list of list (only two nested level):
my_list = [['A'], ['B'], ['C','D','A','B'], ['E'], ['B', 'F', 'G'], ['H']]
I've a list of items to delete in my_list:
to_del = ['A','B']
this is my idea of code to delete to_del elements from my_list:
for i in my_list:
for d in to_del:
if d in i:
i.remove(d)
Output:
[[], [], ['C', 'D'], ['E'], ['F', 'G'], ['H']]
Here my questions:
Can you suggest a more pythonic/elegant way to do the same
Can you suggest a smart way to generalize the number of nested levels
e.g my_list = [ ['A'], ['B'], ['C', ['D', 'E', ['F']], 'G'], ['H'] ]
The ideal method will have a boolean argument empty_lists to decide whether or not keep empty lists.

Try list comprehension:
my_list = [[x for x in sublist if x not in to_del] for sublist in my_list]
Output:
>>> my_list
[[], [], ['C', 'D'], ['E'], ['F', 'G'], ['H']]

With nested list comprehensions:
[[y for y in x if y not in to_del] for x in my_list]
With list comprehension and lambda filter:
[filter(lambda y: y not in to_del, x) for x in my_list]
An attempt for the general case of arbitrarily nested lists:
def f(e):
if not isinstance(e,list):
if e not in to_del:
return e
else:
return filter(None,[f(y) for y in e])
to_del = ['A','B']
my_list= [['A'], ['B',['A','Z', ['C','Z','A']]], ['C','D','A','B'],['E'], ['B','F','G'], ['H']]
>>> f(my_list)
[[['Z', ['C', 'Z']]], ['C', 'D'], ['E'], ['F', 'G'], ['H']]

Related

merge nested list by first value in each list in python

I have a version of this code working but it seems overly complex. This is the simplified version im getting stuck on. in python3.
list1 = [['a', 'b'], ['a', 'c'], ['a', 't'], ['x', 'f'], ['x', 'g'], ['d', 'z']]
z = len(list1)
for i in range(0, z):
for j in range(i + 1, z):
while list1[i][0] == list1[j][0]:
list1[i] = list1[i] + [list1[j][-1]]
if list1[j] in list1:
list1.remove(list1[j])
z = z - 1
I want output.
[['a', 'b', 'c', 't'], ['x', 'f', 'g'], ['d', 'z']]
Modding Darryl's a bit:
d = {}
for head, *tail in lst:
d.setdefault(head, [head]).extend(tail)
lst2 = list(d.values())
A simplfied construction is the following two steps.
d = {}
for sublist in lst:
d.setdefault(sublist[0], []).extend(sublist[1:])
lst2 = [[k] + v for k, v in d.items()]
print(lst2)
>>> [['a', 'b', 'c', 't'], ['x', 'f', 'g'], ['d', 'z']]
Explanation
(1) Dictionary d places items with the same first element as a dictionary key, with values corresponding to the remaining elements to produce:
{'a': ['b', 'c', 't'], 'x': ['f', 'g'], 'd': ['z']}
(2) Next, the list comprehension uses the key of each dictionary entry as the first element of a sublist and the value of the items as the remaining elements to produce the desired result

Python - finding all possible grouping of elements in a list

I am trying to find a nice Pythonic way for finding all possible combinations of splitting a list into two groups, as in the following example:
my_array = [A,B,C]
The output should be:
[[[A],[B]]
[[A],[B,C]]
[[A],[C]]
[[A,B],[C]]
[[A,C],[B]]
[[B],[A]]
[[B],[A,C]]
[[B],[C]]
[[B,C],[A]]
[[C],[A]]
[[C],[A,B]]
[[C],[B]]]
Thanks!
Maybe this is what you need:
import itertools
my_array = ['A','B','C']
combos = []
for i in range(1,len(my_array)):
combos += itertools.combinations(my_array, i)
result = []
for c1 in combos:
curr = list(c1)
for c2 in combos:
if not any(i in curr for i in c2):
result.append([curr, list(c2)])
result
#[[['A'], ['B']],
# [['A'], ['C']],
# [['A'], ['B', 'C']],
# [['B'], ['A']],
# [['B'], ['C']],
# [['B'], ['A', 'C']],
# [['C'], ['A']],
# [['C'], ['B']],
# [['C'], ['A', 'B']],
# [['A', 'B'], ['C']],
# [['A', 'C'], ['B']],
# [['B', 'C'], ['A']]]

Joint nested list in Python

How to convert a nested list like below?
d = [[['a','b'], ['c']], [['d'], ['e', 'f']]]
-> [['a','b','c'], ['d','e','f']]
I found a similar question. But it's a little different.
join list of lists in python [duplicate]
Update
Mine is not smart
new = []
for elm in d:
tmp = []
for e in elm:
for ee in e:
tmp.append(ee)
new.append(tmp)
print(new)
[['a', 'b', 'c'], ['d', 'e', 'f']]
Lots of ways to do this, but one way is with chain
from itertools import chain
[list(chain(*x)) for x in d]
results in:
[['a', 'b', 'c'], ['d', 'e', 'f']]
sum(ls, []) to flatten a list has issues, but for short lists its just too concise to not mention
d = [[['a','b'], ['c']], [['d'], ['e', 'f']]]
[sum(ls, []) for ls in d]
Out[14]: [['a', 'b', 'c'], ['d', 'e', 'f']]
This is a simple solution for your question
new_d = []
for inner in d:
new_d.append([item for x in inner for item in x])

Concatenate a list of lists excluding one index

Is there a Pythonic way for concatenating a list of lists, excluding an index of choice? For example, if I had
[['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
and did not want index 1 in the result, my concatenated list would look like:
['a', 'd', 'e', 'f', 'g']
I could do this with a loop and checking against the iteration against my index of choice, but I'm hoping there's a cleaner way.
You can use slicing:
from itertools import chain
ls = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
list(chain.from_iterable(ls[:1] + ls[2:]))
If you want to avoid the cost of adding the slices together and creating new lists, it gets a bit more complicated:
from itertools import chain, islice
list(chain.from_iterable(chain(islice(ls, 1), islice(ls, 2, None))))
Here is one way:
lists = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
subset = [x for ind, x in enumerate(lists) if ind != 1]
subset # [['a'], ['d'], ['e', 'f', 'g']]
flattened = [item for l in subset for item in l]
flattened # ['a', 'd', 'e', 'f', 'g']
You could combine these into a single comprehension, I did it in two steps here to show more clearly what each part does.
this is ~ "I could do this with a loop and checking against the iteration against my index of choice...."
but in a list comprehension, no libs
nix = 1
myls = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
[e for ls in myls for e in ls if ls != myls[nix]]
Out[11]: ['a', 'd', 'e', 'f', 'g']
no need for enumerate either
another of the slice and flatten possibilities that reads nice
sum(myls[:nix] + myls[nix+1:],[])
but some have a problem with the use of sum that way https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/
If you don't mind using an external library I could offer remove and flatten from iteration_utilities1:
>>> from iteration_utilities import remove, flatten
>>> l = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
>>> list(flatten(remove(l, 1)))
['a', 'd', 'e', 'f', 'g']
1 I'm the author of that library.

Python, remove all numbers from sublist

I have the following list: [['F', 'G', 'C'], ['S', 3, 7], ['C', 3, 'D']] (made up of 3 sublists)
But I want to have: [['F', 'G', 'C'], ['S'], ['C', 'D']]
How would I go about doing this?
Use a list comprehension:
my_list = [['F', 'G', 'C'], ['S', 3, 7], ['C', 3, 'D']]
no_numbers = [[item for item in sub_list if not isinstance(item, int)]
for sub_list in my_list]
print(no_numbers)
This prints:
[['F', 'G', 'C'], ['S'], ['C', 'D']]
This is a code of Python 3:
mylist = [['F','G','C'], ['S',3,7], ['C',3,'D']]
rslist = [[y for y in x if not isinstance(y, int)] for x in mylist ]
print (rslist)
mylist = [['F', 'G', 'C'], ['S', 3, 7], ['C', 3, 'D']]
newlist = [[x for x in mysublist if not isinstance(x, int)] for mysublist in mylist]
print newlist
There are multiple ways to acheive this. The above example is using list comprehension.

Categories

Resources