Python - remove duplicate of dict that contains list of lists - python

suppose training_data is a dict that contains a list of lists
such as {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
I want to merge each value in training_data and then flatten it once to a list so that it will become [[1,2,3,5],[1,5,6],[7,5]].

you can achieve the same result with a one-line comprehension, chaining and using a set + sort
import itertools
d = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
result = [sorted(set(itertools.chain.from_iterable(v))) for v in d.values()]
print(result)
outputs:
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]

If you only need unique elements from the list without maintaining the order of elements in initial list, then you may use set here with itertools.chain.from_iterable. You may use these with list comprehension to achieve your desired list as:
>>> from itertools import chain
>>> my_dict = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
>>> [list(set(chain.from_iterable(v))) for v in my_dict.values()]
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]
Note: since dictionaries are unordered in Python <3.6, the order of sub-lists in the resultant lists might differ.
For preserving the order of elements in the sublist while merging, take a look at: Pythonic way to merge two overlapping lists, preserving order

I found a possible solution, but could anyone tell me if there's a simpler way?
training_data = list(chain.from_iterable([transaction for _, transaction in training_data.items()]))
new_training_data = []
for transaction in training_data:
t = set()
for i in transaction:
t = t.union(i)
new_training_data.append(list(t))

You can use set with list comprehension:
training_data = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
resultList = [sorted(set(elem for subList in training_data[key] for elem in subList)) for key in training_data.keys()]
print(resultList)
Output:
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]

Related

how to classify a list of lists by elements length?

I have a list of lists, looks like this :
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
I want to classify the list elements according to their length, so the result looks like this:
2ElelmentSublist=[[1,3],[4,7]]
4ElementSublist=[[3,4,7,9],[2,4,5,3]]
....
And so on.
I read a post about itertools.groupby(),
But I couldn’t figure out how to apply it in my case.
Any pythonic way to do so?
Note: no need to have the result in separate variables,I need a way to know how many types of lengths I have, and a way to reach every group separately.
Thank you in advance.
You can't make lists with dynamic names to be decided at run-time (like your 2ElementSublist or so.)
But you can design a dictionary with keys as length, and values as lists of lists.
Try this:
result = {}
for L in List:
result.setdefault(len(L), list()).append(L)
print(result)
and you will see
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
.setdefault(k, d) either gives you access to the dictionary value of key k, or initialize with a default value d. And you append each list.
Might not be the most pythonic, but you can call values similar to how you wanted.
x = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
dic = {f"{len(i)}_elelment": [] for i in x}
for i in x:
dic[f"{len(i)}_elelment"].append(i)
# {'2_elelment': [[1, 3], [4, 7]],
# '4_elelment': [[3, 4, 7, 9], [2, 4, 5, 3]],
# '3_elelment': [[5, 7, 4]]}
Since you have mentioned you need the list grouped by len and need them in seperate variable I think you will be needing a dict as your final output.
from itertools import groupby, chain
from collections import defaultdict
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
res = defaultdict(list)
for _, v in groupby(sorted(List, key=len)):
l = list(chain(*v))
res[len(l)].append(l)
# Output : defaultdict(list,
{2: [[1, 3], [4, 7]],
3: [[5, 7, 4]],
4: [[3, 4, 7, 9], [2, 4, 5, 3]]})
You can try this:
List = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
sizes = set([(len(element)) for element in List])
result = {}
for element in List:
if len(element) not in result.keys():
result[len(element)] = []
result[len(element)].append(element)
print(result)
And result is:
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
Use groupby by len:
Ex:
from itertools import groupby
lst = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
print( [list(v) for k, v in groupby(sorted(lst, key=len), key=len)] )
#or
print( {k: list(v) for k, v in groupby(sorted(lst, key=len), key=len)} )
Output:
[[[1, 3], [4, 7]], [[5, 7, 4]], [[3, 4, 7, 9], [2, 4, 5, 3]]]
{2: [[1, 3], [4, 7]], 3: [[5, 7, 4]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]]}

Get all possible permutation of a list with list comprehension in python? [duplicate]

This question already has an answer here:
Name is not defined in a list comprehension with multiple loops
(1 answer)
Closed 1 year ago.
I've referenced this question How to generate all permutations of a list in Python, where I faced a similar scenario that expressed in this question.
This time, I wanna generate all possible permutations(without an empty list [])of a list , and store it in another single list. E.g. the target list is a_list=[1, 2, 3], and I want something like:
[
[1], [2], [3],
[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2],
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]
]
I've tried this code, which worked successfully (using built-in itertools module):
import itertools
perm = list()
for i in range(1, len(a_list) + 1):
perm.extend([list(x) for x in itertools.permutations(a_list, i)])
I wanna to try it in a list comprehension way, but I failed with this attempt:
perm = [list(x) for x in permutations(a_list, i) for i in range(1, len(a_list)+1)]
So is there any feasible list comprehension method to do this stuff?
As the comments say, you have mixed up the order of the for loops. The first for is the outer loop, the second for is the inner loop (read left to right in a list comprehension).
This is the correct ordering:
import itertools
a_list=[1, 2, 3]
perm = [list(x) for i in range(1, len(a_list)+1) for x in itertools.permutations(a_list, i)]
print(perm)
>>>[[1], [2], [3],
[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2],
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Get unique elements from list of lists when the order of the sublists does not matter

I have a list of pairs, representing all edges of cluster in a graph. Actually the list is bigger than this. This is just an example.
[[1, 2], [2, 1], [3, 5], [6, 3], [3, 6]]
[1, 2] means an edge between nodes 1 and 2, and so does [2, 1].
So, I have some difficulty to eliminate the repeated pairs to count the in-degrees of the cluster.
The output should be like [[1, 2], [3, 5], [3, 6]] or [[2, 1], [3, 5], [6, 3]]
If order of the pairs' elements is irrelevant, then use sorted to normalize pairs. Then, use a set to eliminate duplicates.
lst = [1, 2], [2, 1], [3, 5], [6, 3], [3, 6]
unique_pairs = {tuple(sorted(p)) for p in lst} # {(1, 2), (3, 6), (3, 5)}
To remove duplicates whilst preserving order, you can key off a dict:
>>> data = [1, 2], [2, 1], [3, 5], [6, 3], [3, 6]
>>> list({frozenset(edge): edge for edge in data}.values())
[[2, 1], [3, 5], [3, 6]]
Order is preserved overall, and also the order within each pair. In case of dupes, the last pair seen will be the one kept in result. You could keep the first pair by reversed iteration:
>>> list({frozenset(edge): edge for edge in reversed(data)}.values())[::-1]
[[1, 2], [3, 5], [6, 3]]
If you have an older version of Python (<3.6) where the standard dict is not order-preserving, then do the same using an OrderedDict:
>>> from collections import OrderedDict
>>> list(OrderedDict((frozenset(edge), edge) for edge in data).values())
[[2, 1], [3, 5], [3, 6]]

Permutations within and across list of lists [python]

There are many questions that are related but none that I could find to do exactly what I am looking for. Essentially, I want to get all permutations of each sub-list put together for all possible combinations but keeping them separate. As such:
input=[[1,2,3],[4],[5,6]]
desired output:
[[1,2,3],[4],[6,5]]
[[2,1,3],[4],[5,6]]
[[2,1,3],[4],[5,6]]
[[3,1,2],[4],[5,6]]
etc...
I believe the following code will work, but I was wondering if there were any more efficient or succinct strategies. Thank you very much.
input=[[1,2,3],[4],[5,6]]
all_lists=[]
for i in xrange(len(input)):
all_lists.append(list(itertools.permutations(input[i])))
all_combinations = list(itertools.product(*all_lists))
## concat them together
combinations_combined = [list(itertools.chain(*a)) for a in all_combinations]
We can first use list comprehension to generate all permutations for each sublist:
perms = [list(map(list,permutations(subl))) for subl in data]
and then we can use product to obtain products.
for data in product(*perms):
print(list(data))
Or in full:
from itertools import permutations, product
def product_perms(data):
perms = [list(map(list,permutations(subl))) for subl in data]
for data in product(*perms):
print(list(data))
This produces:
>>> product_perms(data)
[[1, 2, 3], [4], [5, 6]]
[[1, 2, 3], [4], [6, 5]]
[[1, 3, 2], [4], [5, 6]]
[[1, 3, 2], [4], [6, 5]]
[[2, 1, 3], [4], [5, 6]]
[[2, 1, 3], [4], [6, 5]]
[[2, 3, 1], [4], [5, 6]]
[[2, 3, 1], [4], [6, 5]]
[[3, 1, 2], [4], [5, 6]]
[[3, 1, 2], [4], [6, 5]]
[[3, 2, 1], [4], [5, 6]]
[[3, 2, 1], [4], [6, 5]]
In case you want to return such a list, you can use:
def product_perms(data):
perms = [list(map(list,permutations(subl))) for subl in data]
return [list(data) for data in product(*perms)]
And_the_case [[3, 1, 2], [4], [5, 6, [7,8[9,10,11]]? If it's nested list?

Python: Removing list with repeated elements in a list of lists

I have a list of lists as follows:
seq = [[2, 5], [1, 4], [1, 2], [3, 4], [1, 5], [2, 3], [3, 5], [1, 1], [2, 4], [1, 3]]
How do I remove the list inside this list which have repeated elements i.e. [1, 1]?
For this specific case:
[i for i in seq if i[0] != i[-1]]
More generally, remove sublists where all items are equivalent (kudos #A-B-B 8' comment):
[i for i in seq if len(set(i)) > 1]
Finally, if any replicates are found within a sublist, e.g. [..., [1, 2, 2]]:
import collections as ct
[i for i in seq if i and all(v == 1 for v in ct.Counter(i).values())]
Tests using the final solution:
def drop_replicates(seq):
return [i for i in seq if i and all(v == 1 for v in ct.Counter(i).values())]
assert drop_replicates([[2, 5], [1, 1], [2, 4]]) == [[2, 5], [2, 4]]
assert drop_replicates([[2, 5], [1, 1], [2, 4], [1, 2, 2]]) == [[2, 5], [2, 4]]
assert drop_replicates([[2, 5], [1, 1], [2, 4], [1, 2, 2], []]) == [[2, 5], [2, 4]]
set(i) converts the list to a set. Sets are unordered lists without duplicates (same as mathematical sets). Following is a more generic solution, it should work with any number of elements in the child lists.
[i for i in seq if len(set(i)) == len(i)]

Categories

Resources