2

I have this dictionary:

>>> times
{'time':[0,1,0], 'time_d':[0,1,0], 'time_up':[0,0,0]}

I want to make this output, the order of the values matters!:

0 1 0 0 1 0 0 0 0
# 0 1 0 | 0 1 0 | 0 0 0     ===   time | time_d | time_up   items of the list

For been more exactly I want a list like this:

[0,1,0,0,1,0,0,0,0]

Not use print().

Without a list comprehension I can do:

tmp = []
for x in times.values():
    for y in x:
        tmp.append(y)

I tryied using some list comprehensions but anyone works, like this two:

>>> [y for x in x for x in times.values()]
[0,0,0,0,0,0,0,0,0]

>>> [[y for x in x] for x in times.values()]
[[0,0,0],[0,0,0],[0,0,0]

How can I solve this with in one line (list comprehension))?

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
Ender Look
  • 2,303
  • 2
  • 17
  • 41
  • Does order matter based on your expected output? – idjaw Jul 22 '17 at 02:36
  • You cannot guarantee order with a `dict`... – juanpa.arrivillaga Jul 22 '17 at 02:37
  • 1
    Yes, but if order *does* matter, then maybe it's a matter of using the appropriate key to get that order. That is why the question is being asked. – idjaw Jul 22 '17 at 02:38
  • @idjaw, mmm, yes, for been exactly with the result I will write: `print('Time: {}:{}:{} / {}:{}:{} ({}:{}:{})'.format(INSERT HERE THE LIST COMPREHENSION))`. – Ender Look Jul 22 '17 at 02:38
  • Yeah, so actually, you can just use `sorted` and the keys will come back in the order you want, but you'll have to keep that in mind when naming the keys..., in which case something like `[i for _, v in sorted(times.items()) for i in v]`. – juanpa.arrivillaga Jul 22 '17 at 02:40
  • 1
    But for the record, the equivalent list comprehension to your for-loop is simply `[y for x in times.values() for y in x]`, but note, this is not guaranteed to give the output you want, since you cannot guarantee the order of a dictionary. – juanpa.arrivillaga Jul 22 '17 at 02:43

4 Answers4

3

You already know what values you want based on your dictionary, so just stick to being explicit about what you want from your dictionary when crafting your list:

d = {'time':[0,1,0], 'time_d':[0,1,0], 'time_up':[0,0,0]}
v = [*d['time'], *d['time_d'], *d['time_up']]
print(v)

Output:

[0, 1, 0, 0, 1, 0, 0, 0, 0]
idjaw
  • 25,487
  • 7
  • 64
  • 83
2

If I understood the question, you have to take the values, and then flat:

Edit, with users @juanpa.arrivillaga and @idjaw I think I undertand better the question, if the order matters, so you can use orderedDict:

import collections

times = collections.OrderedDict()

times['time'] = [0,1,0]
times['time_d'] = [0,1,0]
times['time_up'] = [0,0,0]

def get_values(dic):
  return [value for values in times.values() for value in values]


print(get_values(times))

Now, if you change the dict, the result came in order:

times['time_up2'] = [0,0,1]

get_values(times)

it gives me:

[0, 1, 0, 0, 1, 0, 0, 0, 1]

If the order doesn't matter:

times = {'time':[0,1,0], 'time_d':[0,1,0], 'time_up':[0,0,0]}

def get_values(dic):
  return [value for values in times.values() for value in values]


print(get_values(times))
developer_hatch
  • 15,898
  • 3
  • 42
  • 75
  • 1
    You're not guaranteeing the expected order of the output required with that. – idjaw Jul 22 '17 at 02:42
  • @idjaw ? But the output was like I want, what is wrong? Sorry I am not good in that stuff. – Ender Look Jul 22 '17 at 02:45
  • @EnderLook **Because dictionaries do not guarantee order** – juanpa.arrivillaga Jul 22 '17 at 02:47
  • @idjaw if the dict is not modified, the order is untouched https://stackoverflow.com/questions/2053021/is-the-order-of-a-python-dictionary-guaranteed-over-iterations – developer_hatch Jul 22 '17 at 02:47
  • @DamianLattenero but it is not guaranteed to be *any order*, just that the order *wont change if the dict isn't modified*. So there is no guarantee that this code will give this result every time it is run. – juanpa.arrivillaga Jul 22 '17 at 02:48
  • 1
    For example, copy-pasting your code gives `[0, 1, 0, 0, 0, 0, 0, 1, 0]` on my machine. – juanpa.arrivillaga Jul 22 '17 at 02:49
  • @DamianLattenero mmm, the dict will be all the time changing, for been exactly that is counting time, the numbers inside will grow up. That matter? – Ender Look Jul 22 '17 at 02:49
  • Exactly. That is why it is never wise to depend on that. You will be modifying data in your dictionary, and the nature of the dictionary pre python 3.6 will NEVER guarantee order. If you want order, you can use collections OrderedDict. – idjaw Jul 22 '17 at 02:50
  • mmmm ok... I understand the issue now, thanks, I'm comming up with a better solution :D – developer_hatch Jul 22 '17 at 02:51
  • 1
    @EnderLook if you *don't change the dictionary* the dict order won't change. If you change the lists *inside the dictionary* that doesn't matter. However, **you cannot rely on this solution because dictionaries are inherently unordered** – juanpa.arrivillaga Jul 22 '17 at 02:51
  • @idjaw, I use the last version, python 3.6, this means that my dict is *fine*? – Ender Look Jul 22 '17 at 02:51
  • @EnderLook you should *still not rely on this* in Python 3.6. Indeed, it is explicitely stated that it is currently only an implementation detail, not a guarantee. For now, just use a `collections.OrderedDict` if you want an ordered dictionary. – juanpa.arrivillaga Jul 22 '17 at 02:52
  • For more information read [here](https://stackoverflow.com/questions/39980323/dictionaries-are-ordered-in-python-3-6). But overall, yes, unless it is stated that you are 100% guaranteed all the time ordered insertion in to a dictionary, don't fully trust it and stick what does in fact always guarantee that. – idjaw Jul 22 '17 at 02:53
  • @EnderLook Let me know if that is what you spected – developer_hatch Jul 22 '17 at 03:01
  • @idjaw with your help and juanpa I think I got it, would you check it out? – developer_hatch Jul 22 '17 at 03:03
  • Perfect, thanks! but sorry I don't understand a thing: why times.items() is in the middle and not in the right of the line? I don't understand how to "read" that or the values "move" inside the comprehension. – Ender Look Jul 22 '17 at 03:12
  • @EnderLook Then why did you accept the answer? That indicates that everything is resolved, you understood and accepted the answer and it fixed your problem. – idjaw Jul 22 '17 at 03:14
  • @idjaw, uh, I usually accept the answer when my problem is solved and I put the upvote when I understand the solution. – Ender Look Jul 22 '17 at 03:15
  • @EnderLook Your edit suggestion is fine, if you swap the vals from the list, like this: [value for values in values for value in times.values()] you clairly can see that the list values is not defined, can you see it? The order of the list is from left to the right, and the "values" came from the right to the left – developer_hatch Jul 22 '17 at 03:22
  • Mmm.... I think that I found what are you saying, I found that values isn't defined but I can't "see" how values at the end works. I discover that the order of `value for values in times.values() for value in values` is the same order of a normal iteration: `for values in times.values(): for value in values: print(value)` Maybe I can remember that! Thanks +1. **PS:** If I were you I would also write in the answer the old answer (without OrderedDict) like another less used (and acuracy) solution. – Ender Look Jul 22 '17 at 03:37
0

This will work also in Python 2:

[x for k in 'time time_d time_up'.split() for x in times[k]]
VPfB
  • 14,927
  • 6
  • 41
  • 75
0

Take key and value from dictionary and append it into a list.

times={'time':[0,1,0], 'time_d':[0,1,0], 'time_up':[0,0,0]}
aa=[]
for key,value in times.iteritems():
    aa.append(value)
bb = [item for sublist in aa for item in sublist] #Making a flat list out of list of lists in Python
print bb

Output:

[0, 1, 0, 0, 0, 0, 0, 1, 0]
Rohit-Pandey
  • 2,039
  • 17
  • 24