How to get max() to return the first and second highest value in priority

Question:

I’m working on a personality system for my game. Basically I’m trying to return the two highest values in a list without altering the list.

social_sum = 0
morals_sum = 0
perception_sum = 0
boldness_sum = 0
for trait in self.traits:
    for personality in trait.personality:
        social_sum += personality.social
        morals_sum += personality.morals
        perception_sum += personality.perception
        boldness_sum += personality.boldness
                
personality_list = [social_sum, morals_sum, perception_sum, boldness_sum]

There are 4 types of personalities (which may be positive or negative). The top two highest absolute values of those personalities will determine the persona of a character.

I’ve tried manually by using remove() and then doing the max() function again to return the second highest value. But that will alter personality_list and create other problems down the line. Here’s my code, sorry if it looks really repetitive as I’m still learning the ropes.

print(personality_list)
personality_list = [abs(social_sum), abs(morals_sum), abs(perception_sum), abs(boldness_sum)]
print(personality_list)
first_personality = max(personality_list)

for fp in personality_list:
    if first_personality == social_sum:
        fp = "Extrovert"
    elif -first_personality == social_sum:
        fp = "Introvert"
    elif first_personality == morals_sum:
        fp = "Idealist"
    elif -first_personality == morals_sum:
        fp = "Pragmatic"
    elif first_personality == perception_sum:
        fp = "Upright"
    elif -first_personality == perception_sum:
        fp = "Relaxed"
    elif first_personality == boldness_sum:
        fp = "Dominant"
    elif -first_personality == boldness_sum:
        fp = "Submissive"

print(fp)
personality_list.remove(first_personality)
print(personality_list)

second_personality = max(personality_list)

for sp in personality_list:
    if second_personality == social_sum:
        sp = "Extrovert"
    elif -second_personality == social_sum:
        sp = "Introvert"
    elif second_personality == morals_sum:
        sp = "Idealist"
    elif -second_personality == morals_sum:
        sp = "Pragmatic"
    elif second_personality == perception_sum:
        sp = "Upright"
    elif -second_personality == perception_sum:
        sp = "Relaxed"
    elif second_personality == boldness_sum:
        sp = "Dominant"
    elif -second_personality == boldness_sum:
        sp = "Submissive"
        
print(sp)

If the numbers align correctly the code works. Here is an example of the output:

[-35, -25, 10, 10]
[35, 25, 10, 10]
Introvert
[25, 10, 10]
Pragmatic

If there are two second highest numbers, the output still prioritize the list’s index, which is what I want:

[5, 0, 35, -5]
[5, 0, 35, 5]
Upright
[5, 0, 5]
Extrovert

But if there are two equal absolute highest numbers, the indices obtained through maxing the output while removeing the one already used will not be correct:

[-5, -20, 20, 5]
[5, 20, 20, 5]
Upright
[5, 20, 5]
Upright

Any advice is appreciated. Thanks!

Asked By: Deimos96

||

Answers:

My solution with sorting the list would be

from typing import List

personalities: List[List[str]] = [
    ["Extrovert", "Introvert"],
    ["Idealist", "Pragmatic"],
    ["Upright", "Relaxed"],
    ["Dominant", "Submissive"]
]

score: List[int] = [-5, -20, 20, 5]
sorted_indices: List[int] = [i[0] for i in sorted(enumerate(score), key=lambda k: abs(k[1]), reverse=True)]
for i in range(2): # Number of traits neeeded
    index: int = sorted_indices[i]
    secondary_index: int = 0
    if score[index] < 0:
        secondary_index = 1
    print(p[index][secondary_index])

Here, we get the indexes of the values in the order they would be in a sorted score list, without modifying the list itself, so it shouldn’t impact the program down the line.
The sorting takes place at the declaration of sorted_indices and proceeds as follows: a list of pairs index, value is generated (enumerate(score)), then sorted in reverse according to the absolute value (sorted(enumerate(score), key=lambda k: abs(k[1]), reverse=True)), and finally we get rid of the value part, for we only need the indices (i[0] for i in ...).


Edit: to make a list out of the selected personnalities

from typing import List

personalities: List[List[str]] = [
    ["Extrovert", "Introvert"],
    ["Idealist", "Pragmatic"],
    ["Upright", "Relaxed"],
    ["Dominant", "Submissive"]
]
selected_personalities: List[str] = []

score: List[int] = [-5, -20, 20, 5]
sorted_indices: List[int] = [i[0] for i in sorted(enumerate(score), key=lambda k: abs(k[1]), reverse=True)]
for i in range(2): # Number of traits neeeded
    index: int = sorted_indices[i]
    secondary_index: int = 0
    if score[index] < 0:
        secondary_index = 1
    selected_personalities.append(personalities[index][secondary_index])

print(selected_personalities)
Answered By: GregoirePelegrin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.