[Tutor] Variable change within library depending on user input.

Peter Otten __peter__ at web.de
Mon Mar 4 03:29:35 EST 2019


Harry Oneill wrote:

> Hey there everybody hope your doing great.
> 
> I was here a few months ago and got pointed in the right direction very
> kindly by one of the tutors. Im a little stuck again now and have been
> researching for a while and can't come up with a solution to my problem.
> 
> The below program is designed to take two user inputs, item purchase
> location and sale location and then to compare some dictionaries of those
> locations and calculate the most profitable item to buy.
> 
> Initially i designed this to work with just two locations and am now
> struggling to add a third.

Do you still have the version that works with two locations?
Then start from that with the following steps:

(1) Extract the code that uses a buying and a selling, and finds the most 
profitable good into a function

def find_most_profitable(buying_dict, selling_dict):
    ... # code adapted from the version that works with two locations

(2) Write the main script that picks a buying dict and a selling dict using 
user input. The simplest approach is to put the buying dicts into another 
dict:

buying_dicts = {"olisar": buying_olisar, "levski": buying_levski, "156": 
buying_arc_corp_mining_area_157}
selling_dicts = ...

def pick_dict(choices, prompt):
    print(prompt)
    while True:
        print("Pick one of", ", ".join(sorted(choices)))
        choice = input("> ")
        if choice in choices:
            return choices[choice]

buying =  pick_dict(
    buying_dicts,
    "Were are you planning to buy your goods?"
)
selling = pick_dict(
    selling_dicts,
    "Where are you planning to sell your goods?"
)

find_most_profitable(buying, selling)

As a bonus the pick_dict() function checks the validity of your choice and 
lets you repeat your input if you made a spelling error.

> However they produce this error that i am unsure how to resolve.
> 
> Traceback (most recent call last):
>   File "/home/floppypoppy/PycharmProjects/Star Citizen Trading
>   Program/Star Citizen trading NEW.py", line 33, in <module>
>     tradable_items = common(user_purchase_location_1,
>     user_sale_destination_1)
>   File "/home/floppypoppy/PycharmProjects/Star Citizen Trading
>   Program/Star Citizen trading NEW.py", line 32, in common
>     return set(curr.keys()).intersection(set(other.keys()))
> AttributeError: 'str' object has no attribute 'keys'

Now why did you see the traceback?

> #### Sorting the dict into ascending value instead of alphabetical
> sort_buying_olisar = sorted(buying_olisar, key=lambda tup: tup[1])


Sorting a dict implies iteration, and iterating over a dict produces the 
keys:

>>> d = {"az": 2, "by": 1, "cx": 3}
>>> list(d)
['cx', 'by', 'az']

Therefore

>>> sorted(d, key=lambda k: k[1])
['cx', 'by', 'az']

sorts the keys by the second character.
To sort the (key, value) pairs by value you need to be explicit:

>>> sorted(d.items(), key=lambda kv: kv[1])
[('by', 1), ('az', 2), ('cx', 3)]

If you are using Python 3.7 (and inofficially 3.6 I think) you can convert 
this back into a dict with

items = sorted(d.items(), key=lambda kv: kv[1])
ordered = dict(items)

In older Pythons you may need

ordered = collections.OrderedDict(items)

instead.





More information about the Tutor mailing list