Python Forum
Sorting List - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Sorting List (/thread-36183.html)



Sorting List - finndude - Jan-25-2022

Hi All,

['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
I have this list here. What would I need to do to sort it largest to smallest, based on the numbers, or is this not possible?


RE: Sorting List - ndc85430 - Jan-25-2022

Ignore me, I misread. You can pass a key function to sort or sorted. It will need to split the string to extract the number and use that for sorting.

Do you really need to have the data as a single string? An object would make more sense.


RE: Sorting List - deanhystad - Jan-25-2022

x = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
x.sort(key=lambda x: int(x.split(":")[1]))
print(x)
Output:
['Evie : 0', 'P1 : 0', 'P1 : 0', 'P2 : 5', 'P2 : 5', 'Evie : 5', 'Finley : 10', 'Finley : 15']
Could also use the name for when the score is the same.
x = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
x.sort(key=lambda x: (int(x.split(":")[1]), x))  # Sort key is a tuple(number, name)
print(x)
Output:
['Evie : 0', 'P1 : 0', 'P1 : 0', 'Evie : 5', 'P2 : 5', 'P2 : 5', 'Finley : 10', 'Finley : 15']



RE: Sorting List - Frankduc - Jan-25-2022

(Jan-25-2022, 06:23 PM)deanhystad Wrote:
x = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
x.sort(key=lambda x: int(x.split(":")[1]))
print(x)
Output:
['Evie : 0', 'P1 : 0', 'P1 : 0', 'P2 : 5', 'P2 : 5', 'Evie : 5', 'Finley : 10', 'Finley : 15']
Could also use the name for when the score is the same.
x = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
x.sort(key=lambda x: (int(x.split(":")[1]), x))
print(x)
Output:
['Evie : 0', 'P1 : 0', 'P1 : 0', 'Evie : 5', 'P2 : 5', 'P2 : 5', 'Finley : 10', 'Finley : 15']



Hello dean,

I tried a different approach but cant get to your result. How come?

dt = {'Finley' : 10, 'Evie' : 0, 'P1' : 0, 'P2' : 5, 'P1' : 0, 'P2' : 5, 'Finley' : 15, 'Evie' : 5}

sorted_dt_value = sorted(dt.values())
print(sorted_dt_value)
Output:
[0, 5, 5, 15]
To be more precise it seem to be a list but x is a dictionnary. Used split to get rid of the comma.


RE: Sorting List - deanhystad - Jan-25-2022

How long did you think about this before giving up? You got a list of sorted numbers because you are sorting the values(), not the items(). You would have noticed this if you tried printing dt.values(). Spend more time trying to answer these kind of questions yourself. Your programming skills will increase much faster if you fix your own problems. Debugging is a great teacher. It produces a deeper and wider understanding than somebody giving you the answer.
dt = {'Finley' : 10, 'Evie' : 0, 'P1' : 0, 'P2' : 5, 'P1' : 0, 'P2' : 5, 'Finley' : 15, 'Evie' : 5}

print(dt.values())
Output:
dict_values([15, 5, 0, 5])
Notice that the names (keys) are gone. The are not going to reappear when sorted.

You cannot sort a dictionary, but you can put the items in a list and sort them.
dt = {'Finley' : 10, 'Evie' : 0, 'P1' : 0, 'P2' : 5, 'P1' : 0, 'P2' : 5, 'Finley' : 15, 'Evie' : 5}

sorted_dt = sorted(dt.items(), key=lambda x: (int(x[1]), x[0]))
print(sorted_dt)
Output:
[('P1', 0), ('Evie', 5), ('P2', 5), ('Finley', 15)]
And of course now that dt is a dictionary you cannot have duplicate names (keys). Duplicate keys are replaced, so the dt dictionary is:
dt = {'Finley': 15, 'Evie': 5, 'P1': 0, 'P2': 5}
Once you have a sorted list of items you can use them to construct a dictionary that is sorted.
dt = {'Finley' : 10, 'Evie' : 0, 'P1' : 0, 'P2' : 5, 'P1' : 0, 'P2' : 5, 'Finley' : 15, 'Evie' : 5}
sorted_dt_items = sorted(dt.items(), key=lambda x: (int(x[1]), x[0]))
sorted_dt = {key:value for key, value in sorted_dt_items}
print(sorted_dt)
Output:
{'P1': 0, 'Evie': 5, 'P2': 5, 'Finley': 15}



RE: Sorting List - Frankduc - Jan-25-2022

(Jan-25-2022, 07:06 PM)deanhystad Wrote: Because you are sorting the values, not the items.
dt = {'Finley' : 10, 'Evie' : 0, 'P1' : 0, 'P2' : 5, 'P1' : 0, 'P2' : 5, 'Finley' : 15, 'Evie' : 5}

sorted_dt = sorted(dt.items(), key=lambda x: (int(x[1]), x[0]))
print(sorted_dt)
Output:
[('P1', 0), ('Evie', 5), ('P2', 5), ('Finley', 15)]
And of course now that this is a dictionary you cannot have duplicate names (keys).

But the original list was between [] not {}, of course i changed that because it would not take it.
It does not return duplicate but finley 10 is not, and obviously when filter it return the latters.

ok

TY


RE: Sorting List - ndc85430 - Jan-26-2022

Well yeah, lists and dictionaries have different semantics (and performance characteristics).


RE: Sorting List - Pedroski55 - Jan-26-2022

I thought this was interesting. You end up with a list of named tuples.

from collections import namedtuple
mylist = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
Player = namedtuple('Player', 'name score')
tups = []
for m in mylist:
    alist = m.split()
    name = alist[0]                         
    score = int(alist[2])
    tups.append(Player(name, score))
# sort by name or score
tups.sort(key=lambda x: getattr(x, 'score'), reverse=True)



RE: Sorting List - DeaD_EyE - Jan-27-2022

Example with TypeHints, NamedTuple and closures (nested functions):

from typing import Generator, Iterable, NamedTuple


class ScoreResult(NamedTuple):
    player: str
    score: int


def sort_score(sequence: list[str]) -> list[ScoreResult]:
    def get_elements() -> Generator[ScoreResult, None, None]:
        for element in sequence:
            key, value = element.rsplit(":", maxsplit=1)
            yield ScoreResult(key.strip(), int(value))

    def sorter(item: ScoreResult) -> int:
        return item.score

    return sorted(get_elements(), key=sorter)


mylist = [
    "Finley : 10",
    "Evie : 0",
    "P1 : 0",
    "P2 : 5",
    "P1 : 0",
    "P2 : 5",
    "Finley : 15",
    "Evie : 5",
]


sorted_score = sort_score(mylist)
print(sorted_score)



RE: Sorting List - Pedroski55 - Jan-27-2022

Of course Dead_EyE obviously knows a lot more about this than EyE, sorry I.
Sitting on the train from Shanghai, I came up with this!
I just wanted to cater for input strings which are maybe not uniform. Then I think you need re.
Still, names with non-word characters will cause trouble.

import re

mylist1 = ['Finley : 10', 'Evie : 0', 'P1 : 0', 'P2 : 5', 'P1 : 0', 'P2 : 5', 'Finley : 15', 'Evie : 5']
mylist2 = ['Finley,10', 'Evie,0', 'P1,0', 'P2,5', 'P1,0', 'P2,5', 'Finley,15', 'Evie,5']
mylist3 = ['Fin#1ley#1,10', 'Ev@ie,0', 'P&1,0', 'P&2,5', 'P*1,0', 'P$2,5', 'Finle-y,15', 'Evi!e,5']

# as long as the name is at the start of the string and the number at the end
# and name and number are separated by a non-word character, this should find them.

# finds a word at the beginning of the string using ^
# stops at the first non-word character
pattern1 = re.compile(r'^\w+')
# matches numbers at the end of the string using $
pattern2 = re.compile(r'\d+$')

# having found them, can't be too hard to sort them!


for m in mylist1:
    print('string is', m)    
    match1 = re.search(pattern1, m)
    start = match1.span()[0]
    stop = match1.span()[1] + 1
    name = m[start:stop]
    print('Name is', name)
    match2 = re.search(pattern2, m)
    start = match2.span()[0]
    stop = match2.span()[1] + 1
    score = m[start:stop]
    print('Score is', score, '\n\n')

for m in mylist2:
    print('string is', m)    
    match1 = re.search(pattern1, m)
    start = match1.span()[0]
    stop = match1.span()[1] + 1
    name = m[start:stop]
    print('Name is', name)
    match2 = re.search(pattern2, m)
    start = match2.span()[0]
    stop = match2.span()[1] + 1
    score = m[start:stop]
    print('Score is', score, '\n\n') 

for m in mylist3:
    print('string is', m)    
    match1 = re.search(pattern1, m)
    start = match1.span()[0]
    stop = match1.span()[1] + 1
    name = m[start:stop]
    print('Name is', name)
    match2 = re.search(pattern2, m)
    start = match2.span()[0]
    stop = match2.span()[1] + 1
    score = m[start:stop]
    print('Score is', score, '\n\n')