Home > Software design >  How to keep the original order (without sorting) when converting dictionary to list?
How to keep the original order (without sorting) when converting dictionary to list?

Time:12-30

I have a dictionary {'16022000': 5172863.79, '21349000': 264853.56, '21362000': -5437717.35} and created 4 lists for positive/negative key/values:

list({(g) for g, v in gv.items() if v >= 0})
list({(g) for g, v in gv.items() if v <= 0})
list({(v) for g, v in gv.items() if v >= 0})
list({(v) for g, v in gv.items() if v <= 0})

The results I got when printing the lists were:

['16022000', '21349000']
[264853.56, 5172863.79]
['21362000']
[-5437717.35]

Expecting:

['16022000', '21349000']
[5172863.79, 264853.56]

It seemed that list sorted numbers by value. How can I prevent that?

CodePudding user response:

Problem 1

Standard Python dict has no order; so no, you can't preserve the order, as there is none.

Since Python 3.7 dict has order. (Thankyou snakecharmerb, Vikash)

Problem 2

You are using "set comprehension" syntax: {a for b in thing if condition}

Sets similarly have no order.

Solution

Use an OrderedDict instead of a dict.

Use a list comprehension instead of a set comprehension.

gv = {'16022000': 5172863.79, '21349000': 264853.56, '21362000': -5437717.35})

[g for g, v in gv.items() if v >= 0]
[g for g, v in gv.items() if v <= 0]
[v for g, v in gv.items() if v >= 0]
[v for g, v in gv.items() if v <= 0]

Remark

The only reason the order would matter to you is if you were going to pair the numbers back up after the fact. Have you considered:

[(g, v) for g, v in gv.items() if v >= 0]

or, as a dictionary

{g: v for g, v in gv.items() if v >= 0]

CodePudding user response:

I don't know if you noticed it, but you are actually storing the resultant elements in a set which you are then converting to a list.

Let me break down the code. Let's take line 3 as an example.

print(list({(v) for g, v in gv.items() if v >= 0}))

Now if you remove the list() constructor, you will notice the obvious.

print({(v) for g, v in gv.items() if v >= 0})

Output:

{264853.56, 5172863.79}

You can clearly see that the output is a set.

Why I'm telling you this is because sets are actually unordered. They store every elements in a random order. So, the output is in an order which dosen't make any sense.

So, to fix this problem, try not to store everything in a set, rather store it in a list itself.

print([v for g, v in gv.items() if v >= 0])

Now, the output will be more understandable:

[5172863.79, 264853.56]
  • Related