I need help finding a way in python to get the max N
items in a multi-dimensional python dictionary. For example:
things = {
"car": { "weight": 100 },
"apple": { "weight": 1 },
"spanner": { "weight": 10 }
}
In this case, I would want to find the 2 highest-weighted items in the dictionary, specifically the keys of these items. So in this case, it should return ["car", "spanner"]
Note: This is my first attempt at a genetic algorithm, so I might not be doing it correctly. At all.
As I am British, I am searching for the best cup of tea I can imagine, so I am writing a python program that generates 10 random cups of tea, then uses natural selection to find the top 5 in that ten and so on.
A cup of tea is modelled as a python dictionary, with 5 keys:
{
"brew_time": Some Number,
"milk": Some Number,
"sweeteners": Some Number,
"fitness": Some Number (This is what I'm interested in),
"name": Some randomly generated name (Doesn't really matter)
}
A cup of tea my program will spit out will look something like this:
{'brew_time': 2.0, 'milk': 0.5, 'sweeteners': 3.0, 'name': 'bold cup', 'fitness': 0}
It then generates 10 cups of tea, stored in the teas
variable. This is an example of an output of that:
{0: {'brew_time': 2.0, 'milk': 0.4, 'sweeteners': 1.0, 'name': 'unafraid brew', 'fitness': 0}, 1: {'brew_time': 3.0, 'milk': 0.5, 'sweeteners': 3.0, 'name': 'fire-eating blend', 'fitness': 0}, 2: {'brew_time': 2.0, 'milk': 0.6, 'sweeteners': 2.0, 'name': 'fearless drink', 'fitness': 0}, 3: {'brew_time': 2.0, 'milk': 0.9, 'sweeteners': 3.0, 'name': 'fire-eating blend', 'fitness': 0}, 4: {'brew_time': 2.0, 'milk': 0.8, 'sweeteners': 2.0, 'name': 'fire-eating cuppa', 'fitness': 0}, 5: {'brew_time': 3.0, 'milk': 0.3, 'sweeteners': 1.0, 'name': 'fire-eating drink', 'fitness': 0}, 6: {'brew_time': 4.0, 'milk': 0.7, 'sweeteners': 2.0, 'name': 'dauntless medley', 'fitness': 0}, 7: {'brew_time': 3.0, 'milk': 0.3, 'sweeteners': 2.0, 'name': 'dauntless cuppa', 'fitness': 0}, 8: {'brew_time': 3.0, 'milk': 0.9, 'sweeteners': 2.0, 'name': 'epic drink', 'fitness': 0}, 9: {'brew_time': 2.0, 'milk': 0.4, 'sweeteners': 2.0, 'name': 'gusty drink', 'fitness': 0}}
I'm now trying to code a function called selection()
that will remove the 5 least fit teas from the dictionary. (The fitness of a tea is set by me, using the rank_tea()
function, which takes an array and sets all the teas fitnesses, which is a number between 0 - 1 that represents the quality of the tea)
This is what I've got so far, but it doesn't work:
def selection():
teaCopy = teas.copy()
fitnesses = []
for i in range(0, len(teaCopy)):
fitnesses.append(teas[i]["fitness"])
print(fitnesses)
max_fitnesses_indicies = sorted(range(len(fitnesses)), key=lambda x: fitnesses[x])
print(max_fitnesses_indicies)
len_array = []
print(len_array)
for i in range(0, len(teas)):
len_array.append(i)
to_be_del = list( set(max_fitnesses_indicies) - set(len_array) )
print(to_be_del)
This is the full code. Sorry for the length of the question, I just didn't want to miss anything.
Any help would be appreciated
You can simply use:
>>> sorted(things.keys(),key=lambda x:things[x]['weight'],reverse=True)
['car', 'spanner', 'apple']
To obtain a list of items sorted by their weight (here in reversed order such that the more heavy things are sorted first). So if you call:
>>> sorted(things.keys(),key=lambda x:things[x]['weight'],reverse=True)[:2]
['car', 'spanner']
you get the two heaviest. But this will run in O(n log n). In case the number of values k you wish to obtain is small (compared to the total number). You can use heapq
:
from heapq import nlargest
result = nlargest(k,things.keys(),key=lambda x:things[x]['weight'])
which will - as far as I know - run in O(n log k) (k the numbers of items you want to pick).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With