3

This is what I am doing:

Where data is a list of lists in the form of [[int1, int2, int3], [int1, int2,int3]].

I want a dictionary that looks like: {int1: [int2, int3], in2:[int2, int3]}. I am checking what the size of data is before the dictionary comprehension and it is 1417.

I then check what the length of the dictionary is and it is something like 11, I don't know what is happening to the data list since all of the elements are not being copied into containsBacon.

def makeComprehension(data):
    containsBacon = dict([(movies[2], movies[0:2]) for movies in data])
pp_
  • 3,435
  • 4
  • 19
  • 27
  • Each sub-list contains 3 elements, right? So which element do you want to be the dictionary key, the first or the last? Your description indicates the first, but your code uses `movies[2]` which is the last. Which is correct? – Tom Karzes Feb 26 '16 at 06:06
  • 1
    `containsBacon = dict([(movies[0], movies[1:]) for movies in data])` works – Ananth Feb 26 '16 at 06:07
  • After creating `containsBacon`, do you then intend to return it? Or are you expecting it to be available as a global? If you wish to return it, then you need to add `return containsBacon` to the end. If you expect it to be available in a global, then you need to add `global containsBacon` to the top of the function. Otherwise the function will do nothing. – Tom Karzes Feb 26 '16 at 06:08
  • 1
    You might have duplicated keys which lead to the difference between the length of your list and the length of your dictionary – dazedconfused Feb 26 '16 at 06:09

2 Answers2

0

Here's a way to do it:

>>> l = [[1,2,3], [10,20,30]]
>>> d = {m[0]:m[1:] for m in l}
>>> d
{1: [2, 3], 10: [20, 30]}

Note that not all the elements will be in the resulting dictionary, because if two lists start with the same elements, this will create the same key, and will therefore not appear.

If you want to have all your original elements in your resulting dictionary, you can do the following:

>>> l = [[1,2,3], [10,20,30], [1,5,6]
>>> {m[0]:[x for n in l if n[0]==m[0] for x in n[1:]] for m in l}
{1: [2, 3, 5, 6], 10: [20, 30]}
DevShark
  • 8,558
  • 9
  • 32
  • 56
0

Similar to @DevShark answer, but with destructuring assignment:

>>> L = [[1,2,3], [10,20,30], [1,5,6]]
>>> {k:v for k,*v in L}
{1: [5, 6], 10: [20, 30]}

If you want to concatenate the values for a given key, do not use a dict comprehension:

>>> d = {}
>>> for k,*v in L: d.setdefault(k, []).extend(v)
...
>>> d
{1: [2, 3, 5, 6], 10: [20, 30]}

The setdefault method creates the d[k] entry and set it to an empty list if it does not exist. This solution is O(n) vs O(n^2) in @DevShark answer.

Here's another O(n) version:

>>> import functools
>>> functools.reduce(lambda d,m:{**d, m[0]:d.get(m[0], []) + m[1:]}, L, {})
{1: [2, 3, 5, 6], 10: [20, 30]}

d[m[0]] is updated to its previous value + m[1:]

If you want a dict comprehension, you may use itertools.groupby for a O(n lg n) solution:

>>> import itertools
>>> L.sort() # O(n lg n) part
>>> L
[[1, 2, 3], [1, 5, 6], [10, 20, 30]]
{k:[v for m in ms for v in m[1:]] for k, ms in itertools.groupby(L, lambda m:m[0])}
{1: [2, 3, 5, 6], 10: [20, 30]}
jferard
  • 7,835
  • 2
  • 22
  • 35