Sort a complex Python dictionary by just one of its values

2024/9/24 18:40:29

I am writing a little optimization tool for purchasing stamps at the post office.

In the process I am using a dictionary, which I am sorting according to what I learned in this other "famous" question: Sort a Python dictionary by value

In my case my dictionary is mildly more complex:
- one four-item-tuple to make the key
- and another five-item-tuple to make the data.

The origin of this dictionary is an iteration, where each successful loop is adding one line:

MyDicco[A, B, C, D] = eval, post, number, types, over

This is just a tiny example of a trivial run, trying for 75 cents:
{
(0, 0, 1, 1): (22, 75, 2, 2, 0)
(0, 0, 0, 3): (31, 75, 3, 1, 0)
(0, 0, 2, 0): (2521, 100, 2, 1, 25)
(0, 1, 0, 0): (12511, 200, 1, 1, 125)
(1, 0, 0, 0): (27511, 350, 1, 1, 275)
}

So far I am using this code to sort (is is working):

MyDiccoSorted = sorted(MyDicco.items(), key=operator.itemgetter(1))

I am sorting by my evaluation-score, because the sorting is all about bringing the best solution to the top. The evaluation-score is just one datum out of a five-item-tuple (in the example those are the evaluation-scores: 22, 31, 2521, 12511 and 27511).

As you can see in the example above, it is sorting (as I want it) by the second tuple, index 1. But I had to (grumpily) bring my "evaluation-score" to the front of my second tuple. The code is obviously using the entire second-tuple for the sorting-process, which is heavy and not needed.


Here is my question: How can I please sort more precisely. I do not want to sort by the entire second tuple of my dictionary: I want to target the first item precisely.
And ideally I would like to put this value back to its original position, namely to be the last item in the second tuple - and still sort by it.


I have read-up on and experimented with the syntax of operator.itemgetter() but have not managed to just "grab" the "first item of my second item". https://docs.python.org/3/library/operator.html?highlight=operator.itemgetter#operator.itemgetter

(note: It is permissible to use tuples as keys and values, according to:
https://docs.python.org/3/tutorial/datastructures.html?highlight=dictionary and those are working fine for my project; this question is just about better sorting)


For those who like a little background (you will yell at me that I should use some other method, but I am learning about dictionaries right now (which is one of the purposes of this project)):

This optimization is for developing countries, where often certain values of stamps are not available, or are limited in stock at any given post office. It will later run on Android phones.

We are doing regular mailings (yes, letters). Figuring out the exact postage for each destination with the available values and finding solutions with low stocks of certain values is a not-trivial process, if you consider six different destination-based-postages and hundreds of letters to mail.

There are other modules which help turning the theoretical optimum solution into something that can actually be purchased on any given day, by strategic dialog-guidance...

About my dictionary in this question: I iterate over all reasonable (high enough to make the needed postage and only overpaying up to a fraction of one stamp) combinations of stamp-values.

Then I calculate a "success" value, which is based on the number of stamps needed (priority), the number of types needed (lower priority)(because purchasing different stamps takes extra time at the counter) and a very high penalty for paying-over. So lowest value means highest success.

I collect all reasonable "solutions" in a dictionary where the tuple of needed-stamps serves as the key, and another tuple of some results-data makes up the values. It is mildly over-defined because a human needs to read it at this phase in the project (for debugging).

If you are curious and want to read the example (first line):
The colums are:

  • number of stamps of 350 cents
  • number of stamps of 200 cents
  • number of stamps of 50 cents
  • number of stamps of 25 cents
  • evaluation-score
  • calculated applied postage
  • total number of stamps applied
  • total number of stamp-types
  • over-payment in cents if any

Or in words: (Assuming a postal service is offering existing stamps of 350, 200, 50 and 25 cents), I can apply postage of 75 cents by using 1x 50 cents and 1x 25 cents. This gives me a success-rating of 22 (the best in this list), postage is 75 cents, needing two stamps of two different values and having 0 cents overpayment.

Answer

You can just use a double index, something like this should work:

MyDiccoSorted = sorted(MyDicco.items(), key=lambda s: s[1][2])

Just set 2 to whatever the index is of the ID in the tuple.

https://en.xdnf.cn/q/71567.html

Related Q&A

How to modularize a Python application

Ive got a number of scripts that use common definitions. How do I split them in multiple files? Furthermore, the application can not be installed in any way in my scenario; it must be possible to have…

Solving for quartile and decile using Python

Is there a library for Python 2.7 that can solve quartiles and deciles. It seems that numpy doesnt have any functions for it. Can you give me a link if there are any. Thanks in advance! :D

Predicted values of each fold in K-Fold Cross Validation in sklearn

I have performed 10-fold cross validation on a dataset that I have using python sklearn, result = cross_val_score(best_svr, X, y, cv=10, scoring=r2) print(result.mean())I have been able to get the mean…

What does the comma mean in Pythons unpack?

We can simply use: crc = struct.unpack(>i, data)why do people write it like this: (crc,) = struct.unpack(>i, data)What does the comma mean?

How do I manually add more cookies to a session which already has cookies set in mechanize?

I have a python script which scrapes a page and receives a cookie. I want to append another cookie to the existing cookies that are being send to the server. So that on the next request I have the cook…

python generators time complexity confusion

I have been reading about keyword yield and generators in python and I want to know if I have understood it right it terms of time complexity.Here is my generator function to get factors:def calc_facto…

Python: Find Amount of Handwriting in Video

Do you know of an algorithm that can see that there is handwriting on an image? I am not interested in knowing what the handwriting says, but only that there is one present? I have a video of someone…

Include nonce and block count in PyCrypto AES MODE_CTR

Some background information, you can skip this part for the actual questionthis is my third question about this topic here at stackoverflow. To be complete, these are the other questions AES with crypt…

Why is pandas.series.map so shockingly slow?

Some days I just hate using middleware. Take this for example: Id like to have a lookup table that maps values from a set of inputs (domain) values, to outputs (range) values. The mapping is unique. A …

Viewset create custom assign value in Django Rest Framework

Would like to set a CustomUsers username by using the input email, but where to do the custom assigning, in view? At the same time it receiving a file as well.Models.pyclass CustomUser(AbstractUser):a…