mkc
mkc

Reputation: 11

Lists of list manipulation

My code is the following:

import itertools

lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]

names = [item[0] for item in lists]
for x in lists:
    del x[0]

answer = {name:set(L) for name,L in zip(names, lists)}

which gives me:

{0: {1}, 1: {2, 8}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}

But what I want to have is to add a key of a previous items for each of the entries. What I want is to have

{0:{1},1:{0,2,8},3:{1,4},4:{3,2} (...)}

Futhermore I would like to twist it a little I mean as a key I want to have each number I have on a list e.g. as I have 5:{6,7} i want to have as well 6:{5,7} and 7:{5,6} obviously i should not have any duplicates.

My question is how could i achieve this?

To make myself clearer I want to visualize a the following graph:

LINK

Upvotes: 1

Views: 83

Answers (4)

Alain T.
Alain T.

Reputation: 42143

You could do this with defaultdict from collections:

lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]

from collections import defaultdict
edges  = [ (V[0],Vn) for V in lists for Vn in V[1:] ]
result = next( d for d in [defaultdict(set)] if [d[a].add(b) or d[b].add(a) for a,b in edges])
print( dict(result))
# {0: {1}, 1: {0, 8, 2}, 2: {1, 4, 5}, 8: {1, 9, 10, 11, 12}, 3: {4}, 4: {2, 3}, 5: {2, 6, 7}, 6: {5}, 7: {5}, 9: {8}, 10: {8}, 11: {8}, 12: {8}}

Upvotes: 0

Jab
Jab

Reputation: 27495

I find it unlikely you would want to make a dict of all permutations of each list as you have a duplicate numbers in a couple of them so possibly making a list of all the dicts (of which being the permutations of each list) then you could do this:

from itertools import permutations

lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]

answer = [{k:set(v) for k, *v in perms} for perms in map(permutations, lists)]

Output for this being:

[{0: {1}, 1: {0}}, {1: {8, 2}, 2: {8, 1}, 8: {1, 2}}, {3: {4}, 4: {3}}, {4: {2}, 2: {4}}, {2: {5}, 5: {2}}, {5: {6, 7}, 6: {5, 7}, 7: {5, 6}}, {8: {9, 10, 11, 12}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}]

Otherwise if you don’t mind losing some of the values to being overwritten then you could use this comprehension

answer = {k:set(v) for perms in map(permutations, lists) for k, *v in perms}

Output of this being:

{0: {1}, 1: {8, 2}, 2: {5}, 8: {9, 10, 11, 12}, 3: {4}, 4: {2}, 5: {6, 7}, 6: {5, 7}, 7: {5, 6}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}

Upvotes: 1

jferard
jferard

Reputation: 8180

First of all, you don't need to build a names list: destructuring assignment will do the trick.

>>> lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
>>> answer = {name:set(L) for name,*L in lists}
>>> answer
{0: {1}, 1: {8, 2}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}

Now, you want to add the previous name when you compute the current name:list. You just have to zip the list with itself to get the expected result:

>>> answer = {name2:set([name1]+L2) for (name1,*L1), (name2,*L2) in zip([[lists[0][1]]]+lists, lists)}
>>> answer
{0: {1}, 1: {0, 8, 2}, 3: {1, 4}, 4: {2, 3}, 2: {4, 5}, 5: {2, 6, 7}, 8: {5, 9, 10, 11, 12}}

The trick is to add an element before the first version of the list that will not change the first name:list. If you use [lists[0][1]], the first name1 is part of the first list2 and the set will be unchanged.

Upvotes: 0

Olvin Roght
Olvin Roght

Reputation: 7812

You can use dict comprehension:

lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
answer = {lists[i][0]: set(([lists[i - 1][0]] if i > 0 else []) + lists[i][1:]) for i in range(len(lists))}

Upvotes: 0

Related Questions