Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Sorting List
#1
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?
"Only Boring People Get Bored"
Reply
#2
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.
Reply
#3
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']
BashBedlam likes this post
Reply
#4
(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.
Reply
#5
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}
Frankduc likes this post
Reply
#6
(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
Reply
#7
Well yeah, lists and dictionaries have different semantics (and performance characteristics).
Reply
#8
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)
Reply
#9
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)
Pedroski55 likes this post
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#10
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') 
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  List Sorting Problem ZZTurn 5 1,281 Sep-22-2022, 11:23 PM
Last Post: ZZTurn
  sorting a list of lists by an element leapcfm 3 1,805 Sep-10-2021, 03:33 PM
Last Post: leapcfm
  Sorting list of names using a lambda (PyBite #5) Drone4four 2 2,683 Oct-16-2020, 07:30 PM
Last Post: ndc85430
  list sorting question DPaul 5 2,720 Jun-17-2020, 02:23 PM
Last Post: ndc85430
  sorting list of lists pframe 5 19,620 Apr-17-2020, 09:31 PM
Last Post: Larz60+
  sorting list arian29 2 2,102 Feb-02-2020, 10:31 AM
Last Post: ndc85430
  Converting parts of a list to int for sorting menator01 2 2,188 Nov-03-2019, 03:00 PM
Last Post: menator01
  Sorting a copied list is also sorting the original list ? SN_YAZER 3 2,996 Apr-11-2019, 05:10 PM
Last Post: SN_YAZER
  sorting a list of tuples based on date bluefrog 2 5,727 Aug-10-2018, 02:31 AM
Last Post: ichabod801
  Sorting list of lists with string and int Otbredbaron 6 4,115 May-07-2018, 06:04 AM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020