Reputation: 20587
Okay, so I have a bit of a problem, Im new to python sorry.
I am trying to sort a list by score, which is a number, but if there is a draw I need to sort them by the length of their name, the shorter the name the higher the rank.
So I have this list here
11 Jenny
8 Adam
10 Mark
8 Ada
and when I use this code here on it, it just comes back with
11 Jenny
10 Mark
10 Mark
10 Mark
def sort(names, counts):
newArr = []
newNames = names
newCount = counts
for x in range(0, len(names)):
newArr.append(findBiggest(newNames, newCount))
for z in range(0, len(names)):
name = newArr[len(newArr) - 1].split(" ")[1]
print name
if names[z] == name:
tempArr1 = newNames
tempArr2 = newCount
newNames = []
newCount = []
for y in range(0, len(tempArr1)):
if y != z:
newNames.append(tempArr1[y])
newCount.append(tempArr2[y])
return newArr
def findBiggest(names, counts):
biggest = 0;
for x in range(0, len(counts)):
if int(counts[x]) > biggest:
biggest = int(counts[x])
biggestCountArr = [[], []]
for x in range(0, len(counts)):
if int(counts[x]) == biggest:
biggestCountArr[0].append(counts[x])
biggestCountArr[1].append(names[x])
if len(biggestCountArr[0]) == 1:
return str(biggestCountArr[0][0]) + " " + biggestCountArr[1][0]
else:
return smallestLength(biggestCountArr)
def smallestLength(twoDArr):
names = twoDArr[1]
shortestLen = 0
for x in range(0, len(names)):
if len(names[x]) > shortestLen:
shortestlen = len(names[x])
for x in range(0, len(names)):
if len(names[x]) == shortestLen:
return str(twoDArr[0][x]) + " " + twoDArr[1][x]
Just so you know
11 Jenny
8 Adam
10 Mark
8 Ada
should come out as
11 Jenny
10 Mark
8 Ada
8 Adam
Upvotes: 2
Views: 2278
Reputation: 310247
lst=[(11, "Jenny"),(8, "Adam"),(10, "Mark"),(8, "Ada")]
lst.sort(key=lambda x: (-x[0],len(x[1])) )
print (lst) # [(11, 'Jenny'), (10, 'Mark'), (8, 'Ada'), (8, 'Adam')]
The list method sort
and the builtin function sorted
accept a keyword argument key
which is given a callable. Basically, for every element in the sequence, that element is passed to the key
function and the return value of that function is actually what python uses to determine ordering when sorting. So, in the above, I use lambda
to construct a function which returns a tuple from the input elements. The tuple is ordered first_element, lenth_of_second_element
.
When tuples (or lists for that matter) are compared, it's much like comparing a string. You look at the first element, if they're the same, you continue on to look at the second element, then the third and so on until one element is greater than the other. e.g.
(1,2,3,4) > (1,2,3,3) #True
This ends up being handy for sorting in very interesting ways.
I suppose to round this out, I should mention that the algorithm that python uses to sort is stable. This means that if you sort by keyA and then you sort by keyB, two elements which compare equal based on keyB will maintain the order they had after the sort using keyA. In other words, a sort doesn't change the order of equal valued elements. So, the above could also be accomplished like this:
lst.sort(key=lambda x:len(x[1])) #sort by length of names
lst.sort(key=lambda x:x[0], reversed=True) #sort by score (highest first instead of regular lowest first)
And I suppose no answer is complete without a link to something which explains it more elegantly. (Specifically, see the section on "Key Functions")
Upvotes: 12
Reputation: 1128
aList = [
(11, 'Jenny'),
(8, 'Adam'),
(10, 'Mark'),
(8, 'Ada'),
]
aList.sort(lambda x, y: y[0] - x[0])
print aList
Upvotes: 0
Reputation: 12777
You'd have to iterate over each line and use the sort
method on them
#open the file and read through the lines.
lines = open('yourfile.txt').readlines()
#iterate over each line, and split along the spaces
pairs =[]
for line in lines:
split_string = line.split('')
num = int(split_string[0])
pairs.append((num, split_string[1:])
#sort through the pairs (from mgilsons answer)
pairs.sort(key=lambda x: (x[0],len(x[1]))
edit: actually misread the question.
Upvotes: 0