My objective is to use an insertion sort to sort the contents of a csv file by the numbers in the first column for example I want this:
[[7831703, Christian, Schmidt]
[2299817, Amber, Cohen]
[1964394, Gregory, Hanson]
[1984288, Aaron, White]
[9713285, Alexander, Kirk]
[7025528, Janice, Lee]
[6441979, Sarah, Browning]
[8815776, Rick, Wallace]
[2395480, Martin, Weinstein]
[1927432, Stephen, Morrison]]
and sort it to:
[[1927432, Stephen, Morrison]
[1964394, Gregory, Hanson]
[1984288, Aaron, White]
[2299817, Amber, Cohen]
[2395480, Martin, Weinstein]
[6441979, Sarah, Browning]
[7025528, Janice, Lee]
[7831703, Christian, Schmidt]
[8815776, Rick, Wallace]
[9713285, Alexander, Kirk]]
based off the numbers in the first column within python my current code looks like:
import csv
with open('EmployeeList.csv', newline='') as File:
reader = csv.reader(File)
readList = list(reader)
for row in reader:
print(row)
def insertionSort(readList):
#Traverse through 1 to the len of the list
for row in range(len(readList)):
# Traverse through 1 to len(arr)
for i in range(1, len(readList[row])):
key = readList[row][i]
# Move elements of arr[0..i-1], that are
# greater than key, to one position ahead
# of their current position
j = i-1
while j >=0 and key < readList[row][j] :
readList[row] = readList[row]
j -= 1
readList[row] = key
insertionSort(readList)
print ("Sorted array is:")
for i in range(len(readList)):
print ( readList[i])
The code can already sort the contents of a 2d array, but as it is it tries to sort everything.
I think if I got rid of the [] it would work but in testing it hasn't given what I needed.
To try to clarify again I want to sort the rows positions based off of the first columns numerical value.
Sorry if I didn't understand your need right. But you have a list and you need to sort it? Why you don't you just use sort method in list object?
>>> data = [[7831703, "Christian", "Schmidt"],
... [2299817, "Amber", "Cohen"],
... [1964394, "Gregory", "Hanson"],
... [1984288, "Aaron", "White"],
... [9713285, "Alexander", "Kirk"],
... [7025528, "Janice", "Lee"],
... [6441979, "Sarah", "Browning"],
... [8815776, "Rick", "Wallace"],
... [2395480, "Martin", "Weinstein"],
... [1927432, "Stephen", "Morrison"]]
>>> data.sort()
>>> from pprint import pprint
>>> pprint(data)
[[1927432, 'Stephen', 'Morrison'],
[1964394, 'Gregory', 'Hanson'],
[1984288, 'Aaron', 'White'],
[2299817, 'Amber', 'Cohen'],
[2395480, 'Martin', 'Weinstein'],
[6441979, 'Sarah', 'Browning'],
[7025528, 'Janice', 'Lee'],
[7831703, 'Christian', 'Schmidt'],
[8815776, 'Rick', 'Wallace'],
[9713285, 'Alexander', 'Kirk']]
>>>
Note that here we have first element parsed as integer. It is important if you want to sort it by numerical value (99 comes before 100).
And don't be confused by importing pprint. You don't need it to sort. I just used is to get nicer output in console.
And also note that List.sort() is in-place method. It doesn't return sorted list but sorts the list itself.
*** EDIT ***
Here is two different apporach to sort function. Both could be heavily optimized but I hope you get some ideas how this can be done. Both should work and you can add some print commands in loops to see what happens there.
First recursive version. It orders the list a little bit on every run until it is ordered.
def recursiveSort(readList):
# You don't want to mess original data, so we handle copy of it
data = readList.copy()
changed = False
res = []
while len(data): #while 1 shoudl work here as well because eventually we break the loop
if len(data) == 1:
# There is only one element left. Let's add it to end of our result.
res.append(data[0])
break;
if data[0][0] > data[1][0]:
# We compare first two elements in list.
# If first one is bigger, we remove second element from original list and add it next to the result set.
# Then we raise changed flag to tell that we changed the order of original list.
res.append(data.pop(1))
changed = True
else:
# otherwise we remove first element from the list and add next to the result list.
res.append(data.pop(0))
if not changed:
#if no changes has been made, the list is in order
return res
else:
#if we made changes, we sort list one more time.
return recursiveSort(res)
And here is a iterative version, closer your original function.
def iterativeSort(readList):
res = []
for i in range(len(readList)):
print (res)
#loop through the original list
if len(res) == 0:
# if we don't have any items in our result list, we add first element here.
res.append(readList[i])
else:
done = False
for j in range(len(res)):
#loop through the result list this far
if res[j][0] > readList[i][0]:
#if our item in list is smaller than element in res list, we insert it here
res.insert(j, readList[i])
done = True
break
if not done:
#if our item in list is bigger than all the items in result list, we put it last.
res.append(readList[i])
print(res)
return res
Related
I wrote small program to populate my game with NPCs named by random selections from first name and last name lists.
It worked but sometimes there are duplicate names selected. How can I prevent duplicates?
I could use dict but I prefer list. Is this big disadvantage?
The commented block in adding_male_NPC is my attempt to solve this problem.
import random
women_names = ["Jennifer", "Jenna", "Judith", "Becky", "Kelly"]
man_names = ["Adam", "John", "Jack", "Jim", ]
surnames =["Salzinger", "Jefferson", "Blunt", "Jigsaw", "Elem"]
marriage_status = ["Single", "In couple", "Engaged", "Married", "Divorced", "Widow"]
male_NPCs = []
list = []
def clr_list(list):
del list
def randomizer(list):
random_choice = random.choice(list)
clr_list(list)
return random_choice
def random_male():
male_surname = randomizer(surnames)
male_name = randomizer(man_names)
male_NPC = male_name + " " + male_surname
return (male_NPC)
def add_one_man():
male_NPCs.append(random_male())
return
def addding_male_NPC(count_of_NPC_males):
while count_of_NPC_males > 1:
add_one_man()
# for m in male_NPCs:
# unique_count = male_NPCs.count(m)
# if unique_count > 1:
# male_NPCs.pop(unique)
# count_of_NPC_males +=1
# else:
count_of_NPC_males -= 1
count_of_NPC_males = int(input("How many males should create?: "))
addding_male_NPC(count_of_NPC_males)
print(male_NPCs)
print(len(male_NPCs))
So i tried this but its impossible to count strings or somehow don't use well .count what is most possible.
Get idea to take indexes before creating sum of stings and use it to check double but i feel that i make circles.
I understand that provided list of names and surnames are not guarantee make doubles with high numbers but you got the point of this.
def addding_male_NPC(count_of_NPC_males):
while count_of_NPC_males > 1:
add_one_man()
for m in male_NPCs:
unique_count = male_NPCs.count(m)
if unique_count > 1:
male_NPCs.pop(unique)
count_of_NPC_males +=1
else:
count_of_NPC_males -= 1
Edit
This is so sad :(
mylist = ["a", "b", "a", "c", "c"]
mylist = list(dict.fromkeys(mylist))
print(mylist)
But anyway it will cut planned and needed numbers of item. So question is still active. This answer is quite half answer. I wait for better one.
==========================
Yes! I finally found an answer!
Thank to >>Parnav<< ( he is The guy!)
From his suggestion i made code generating from text file more than i can imagine
import random
import itertools
with open('stock_male_names.txt', 'r') as mn, open('stock_female_names.txt', 'r') as wn, open('stock_surnames.txt', 'r') as sn:
broken_male_names, broken_female_names, broken_surnames = mn.readlines(), wn.readlines(), sn.readlines()
male_names = [name.strip() for name in broken_male_names]
female_names = [name.strip() for name in broken_female_names]
surnames = [name.strip() for name in broken_surnames]
male_persons = [f"{fname} {lname}" for fname, lname in itertools.product(male_names, surnames)]
female_persons = [f"{fname} {lname}" for fname, lname in itertools.product(female_names, surnames)]
print(male_names)
print(len(male_names)) #1001
print(female_names)
print(len(female_names)) #1000
print(surnames)
print(len(surnames)) #1003
print(male_persons)
print(len(male_persons)) #1004003
print(female_persons)
print(len(female_persons)) #1003000
So from three text files of 1k items i made 1kk unique NPC names in almost no load time with open road to expand.
I am amazingly Happy :)
Case closed!
First, we want all possible combinations of the first and last names. We can get this using itertools.product:
import itertools
import random
male_names = [f"{fname} {lname}" for fname, lname in itertools.product(man_names, surname)]
print(male_names)
# ['Adam Salzinger', 'Adam Jefferson', ..., 'John Salzinger', 'John Jefferson', ..., 'Jim Jigsaw', 'Jim Elem']
Since you want to randomly get names from this list, shuffle it.
random.shuffle(male_names)
print(male_names)
# ['Jim Jefferson', 'Jack Jigsaw', 'Adam Jefferson', ..., 'Adam Blunt', 'John Blunt']
Every time you want to add a NPC, pop the last element from this list. Since you shuffled the list earlier, you're guaranteed a random element even if you always pop the last element. Popping the element removes it from the list, so you don't have to worry about duplicates. Take care not to pop more than the list contains (you have indicated elsewhere that this isn't a problem). I prefer to pop from the end of the list because that is an O(1) operation. Popping from a different location would be more expensive.
def add_male_npcs(count=1):
for _ in range(count):
male_NPCs.append(male_names.pop())
At the end, convert the list of strings into a set and then back to a list to remove any duplicates. Then, use the len() function to determine the length of the list compared to the desired length and call the function again this time adding to the list.
If I have a dictionary like this, filled with similar lists, how can I apply a while loo tp extract a list that prints that second element:
racoona_valence={}
racoona_valence={"rs13283416": ["7:87345874365-839479328749+","BOBB7"],\}
I need to print the part that says "BOBB7" for 2nd element of the lists in a larger dictionary. There are ten key-value pairs in it, so I am starting it like so, but unsure what to do because all the examples I can find don't relate to my problem:
n=10
gene_list = []
while n>0:
Any help greatly appreciated.
Well, there's a bunch of ways to do it depending on how well-structured your data is.
racoona_valence={"rs13283416": ["7:87345874365-839479328749+","BOBB7"], "rs13283414": ["7:87345874365-839479328749+","BOBB4"]}
output = []
for key in racoona_valence.keys():
output.append(racoona_valence[key][1])
print(output)
other_output = []
for key, value in racoona_valence.items():
other_output.append(value[1])
print(other_output)
list_comprehension = [value[1] for value in racoona_valence.values()]
print(list_comprehension)
n = len(racoona_valence.values())-1
counter = 0
gene_list = []
while counter<=n:
gene_list.append(list(racoona_valence.values())[n][1])
counter += 1
print(gene_list)
Here is a list comprehension that does what you want:
second_element = [x[1] for x in racoona_valence.values()]
Here is a for loop that does what you want:
second_element = []
for value in racoona_valence.values():
second_element.append(value[1])
Here is a while loop that does what you want:
# don't use a while loop to loop over iterables, it's a bad idea
i = 0
second_element = []
dict_values = list(racoona_valence.values())
while i < len(dict_values):
second_element.append(dict_values[i][1])
i += 1
Regardless of which approach you use, you can see the results by doing the following:
for item in second_element:
print(item)
For the example that you gave, this is the output:
BOBB7
I have an ordered tuple(its 2dimensional, column 0 are my endings, which I want to compare & column1 there are the complete urls), at "column"[0] I have to compare the first value with the second one, if they are the same, save the first value to other list and repeat. I want to compare every item with the following one, if they are euqal or not.
tuple:
[('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT240/a-XH0124KP', '/a-XH0124KP'), ('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT183/a-XH0124KP', '/a-XH0124KP'), ('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT173/a-XH0124KP', '/a-XH0124KP'), ('https://www.topart-online.com/de/Liguster-Zweig-50cm-mit-Glitter/c-KAT184/a-XM0721', '/a-XM0721'), ('https://www.topart-online.com/de/3D-Stern-schwarz-mit-Glitter%2C-7%2C5-cm---SUPER-DEAL/c-KAT14/a-XM1633ZW', '/a-XM1633ZW'), ('https://www.topart-online.com/de/Christbaumschmuck%2C-Zweige%2C-gold-30-cm----SUPER-DEAL/c-KAT14/a-XP0091', '/a-XP0091')]
I want to compare the productnumber extracted of the url, because every product could be possibly found in multiple urls
my sorting try:
sized = len(complete_links2) - 1
for index, tuple in enumerate(complete_links2):
index = k
k = index + 1
if k < sized:
while complete_links2[index][1] == complete_links2[k][1]:
k += 1
if complete_links2[index][1] == complete_links2[k][1]:
k -= 1
not_rep_links.append(complete_links2[index])
complete_links3 = [a_tuple[0] for a_tuple in not_rep_links]
My problem is, that there are some unique links, that get also filter off, because my logic is not really good.
I also tried with set, with unpacking the tuple but idk how to continue
I am still a bit confused but is this what You want?
list_ = [
('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT240/a-XH0124KP', '/a-XH0124KP'),
('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT183/a-XH0124KP', '/a-XH0124KP'),
('https://www.topart-online.com/de/Rose%2C-Micle%2C-kupfer%2C-52cm%2C-Oe-9cm/c-KAT173/a-XH0124KP', '/a-XH0124KP'),
('https://www.topart-online.com/de/Liguster-Zweig-50cm-mit-Glitter/c-KAT184/a-XM0721', '/a-XM0721'),
('https://www.topart-online.com/de/3D-Stern-schwarz-mit-Glitter%2C-7%2C5-cm---SUPER-DEAL/c-KAT14/a-XM1633ZW', '/a-XM1633ZW'),
('https://www.topart-online.com/de/Christbaumschmuck%2C-Zweige%2C-gold-30-cm----SUPER-DEAL/c-KAT14/a-XP0091', '/a-XP0091')
]
products = []
links = []
for item in list_:
if item[1] not in products:
products.append(item[1])
links.append(item[0])
print(links)
I have a code as follows.
for item in my_list:
print(item[0])
temp = []
current_index = my_list.index(item)
garbage_list = creategarbageterms(item[0])
for ele in my_list:
if my_list.index(ele) != current_index:
for garbage_word in garbage_list:
if garbage_word in ele:
print("concepts: ", item, ele)
temp.append(ele)
print(temp)
Now, I want to remove the ele from mylist when it gets appended to temp (so, that it won't get processed in the main loop, as it is a garbage word).
I know it is bad to remove elements straightly from the list, when it is in a loop. Thus, I am interested in knowing if there is any efficient way of doing this?
For example, if mylist is as follows;
mylist = [["tim_tam", 879.3000000000001], ["yummy_tim_tam", 315.0], ["pudding", 298.2],
["chocolate_pudding", 218.4], ["biscuits", 178.20000000000002], ["berry_tim_tam", 171.9],
["tiramusu", 158.4], ["ice_cream", 141.6], ["vanilla_ice_cream", 122.39999999999999]]
1st iteration
for the first element tim_tam, I get garbage words such as yummy_tim_tam and berry_tim_tam. So they will get added to my temp list.
Now I want to remove yummy_tim_tam and berry_tim_tam from the list (because they have already added to temp), so that it won't execute from the beginning.
2nd iteration
Now, since yummy_tim_tam is no longer in the list this will execute pudding. For pudding I get a diffrent set of garbage words such as chocolate_pudding, biscuits, tiramu. So, they will get added to temp and will get removed.
3rd iteration
ice_cream will be selected. and the process will go on.
My final objective is to get three separate lists as follows.
["tim_tam", 879.3000000000001], ["yummy_tim_tam", 315.0], ["berry_tim_tam", 171.9] , ["pudding", 298.2]
["chocolate_pudding", 218.4], ["biscuits", 178.20000000000002], ["tiramusu", 158.4]
["ice_cream", 141.6], ["vanilla_ice_cream", 122.39999999999999]
This code produces what you want:
my_list = [['tim_tam', 879.3], ['yummy_tim_tam', 315.0], ['pudding', 298.2],
['chocolate_pudding', 218.4], ['biscuits', 178.2], ['berry_tim_tam', 171.9],
['tiramusu', 158.4], ['ice_cream', 141.6], ['vanilla_ice_cream', 122.39]
]
creategarbageterms = {'tim_tam' : ['tim_tam','yummy_tim_tam', 'berry_tim_tam'],
'pudding': ['pudding', 'chocolate_pudding', 'biscuits', 'tiramusu'],
'ice_cream': ['ice_cream', 'vanilla_ice_cream']}
all_data = {}
temp = []
for idx1, item in enumerate(my_list):
if item[0] in temp: continue
all_data[idx1] = [item]
garbage_list = creategarbageterms[item[0]]
for idx2, ele in enumerate(my_list):
if idx1 != idx2:
for garbage_word in garbage_list:
if garbage_word in ele:
temp.append(ele[0])
all_data[idx1].append(ele)
for item in all_data.values():
print('-', item)
This produces:
- [['tim_tam', 879.3], ['yummy_tim_tam', 315.0], ['berry_tim_tam', 171.9]]
- [['pudding', 298.2], ['chocolate_pudding', 218.4], ['biscuits', 178.2], ['tiramusu', 158.4]]
- [['ice_cream', 141.6], ['vanilla_ice_cream', 122.39]]
Note that for the purpose of the example I created a mock creategarbageterms function (as a dictionary) that produces the term lists as you defined it in your post. Note the use of a defaultdict which allows unlimited number of iterations, that is, unlimited number of final lists produced.
I would propose to do it like this:
mylist = [["tim_tam", 879.3000000000001],
["yummy_tim_tam", 315.0],
["pudding", 298.2],
["chocolate_pudding", 218.4],
["biscuits", 178.20000000000002],
["berry_tim_tam", 171.9],
["tiramusu", 158.4],
["ice_cream", 141.6],
["vanilla_ice_cream", 122.39999999999999]]
d = set() # remembers unique keys, first one in wins
for i in mylist:
shouldAdd = True
for key in d:
if i[0].find(key) != -1: # if this key is part of any key in the set
shouldAdd = False # do not add it
if not d or shouldAdd: # empty set or unique: add to set
d.add(i[0])
myCleanList = [x for x in mylist if x[0] in d] # clean list to use only keys in set
print(myCleanList)
Output:
[['tim_tam', 879.3000000000001],
['pudding', 298.2],
['biscuits', 178.20000000000002],
['tiramusu', 158.4],
['ice_cream', 141.6]]
If the order of things in the list is not important, you could use a dictionary directly - and create a list from the dict.
If you need sublists, create them:
similarThings = [ [x for x in mylist if x[0].find(y) != -1] for y in d]
print(similarThings)
Output:
[
[['tim_tam', 879.3000000000001], ['yummy_tim_tam', 315.0], ['berry_tim_tam', 171.9]],
[['tiramusu', 158.4]],
[['ice_cream', 141.6], ['vanilla_ice_cream', 122.39999999999999]],
[['pudding', 298.2], ['chocolate_pudding', 218.4]],
[['biscuits', 178.20000000000002]]
]
As #joaquin pointed out in the comment, I am missing the creategarbageterms() functions that groups tiramusu and biscuits with pudding to fit the question 100% - my answer is advocating "do not modify lists in interations, use appropriate set or dict filter it to the groups. Unique keys here are keys that are not parts of later mentioned keys.
You want to have an outer loop that's looping through a list, and an inner loop that can modify that same list.
I saw you got suggestions in the comments to simply not remove entries during the inner loop at all, but instead check if terms already are in temp. This is possible, and may be easier to read, but is not necessarily the best solution with respect to processing time.
I also see you received an answer from Patrick using dictionaries. This is probably the cleanest solution for your specific use-case, but does not address the more general question in your title which is specifically about removing items in a list while looping through it. If for whatever reason this is really necessary, I would propose the following:
idx = 0
while idx < len(my_list)
item = my_list[idx]
print(item[0])
temp = []
garbage_list = creategarbageterms(item[0])
ele_idx = 0
while ele_idx < len(my_list):
if ele_idx != idx:
ele = my_list[ele_idx]
for garbage_word in garbage_list:
if garbage_word in ele:
print("concepts: ", item, ele)
temp.append(ele)
del my_list[ele_idx]
ele_idx += 1
print(temp)
idx += 1
The key insight here is that, by using a while loop instead of a for loop, you can take more detailed, ''manual'' control of the control flow of the program, and more safely do ''unconventional'' things in your loop. I'd only recommend doing this if you really have to for whatever reason though. This solution is closer to the literal question you asked, and closer to your original own code, but maybe not the easiest to read / most Pythonic code.
I would like to sort several points from smallest to biggest however.
I will wish to get this result:
Drogba 2 pts
Owen 4 pts
Henry 6 pts
However, my ranking seems to be reversed for now :-(
Henry 6 pts
Owen 4 pts
Drogba 2 pts
I think my problem is with my function Bubblesort ?
def Bubblesort(name, goal1, point):
swap = True
while swap:
swap = False
for i in range(len(name)-1):
if goal1[i+1] > goal1[i]:
goal1[i], goal1[i+1] = goal1[i+1], goal1[i]
name[i], name[i+1] = name[i+1], name[i]
point[i], point[i + 1] = point[i + 1], point[i]
swap = True
return name, goal1, point
def ranking(name, point):
for i in range(len(name)):
print(name[i], "\t" , point[i], " \t ")
name = ["Henry", "Owen", "Drogba"]
point = [0]*3
goal1 = [68, 52, 46]
gain = [6,4,2]
name, goal1, point = Bubblesort( name, goal1, point )
for i in range(len(name)):
point[i] += gain[i]
ranking (name, point)
In your code:
if goal1[i+1] > goal1[i]:
that checks if it is greater. You need to swap it if the next one is less, not greater.
Change that to:
if goal1[i+1] < goal1[i]:
A bunch of issues:
def Bubblesort - PEP8 says function names should be lowercase, ie def bubblesort
You are storing your data as a bunch of parallel lists; this makes it harder to work on and think about (and sort!). You should transpose your data so that instead of having a list of names, a list of points, a list of goals you have a list of players, each of whom has a name, points, goals.
def bubblesort(name, goal1, point): - should look like def bubblesort(items) because bubblesort does not need to know that it is getting names and goals and points and sorting on goals (specializing it that way keeps you from reusing the function later to sort other things). All it needs to know is that it is getting a list of items and that it can compare pairs of items using >, ie Item.__gt__ is defined.
Instead of using the default "native" sort order, Python sort functions usually let you pass an optional key function which allows you to tell it what to sort on - that is, sort on key(items[i]) > key(items[j]) instead of items[i] > items[j]. This is often more efficient and/or convenient than reshuffling your data to get the sort order you want.
for i in range(len(name)-1): - you are iterating more than needed. After each pass, the highest value in the remaining list gets pushed to the top (hence "bubble" sort, values rise to the top of the list like bubbles). You don't need to look at those top values again because you already know they are higher than any of the remaining values; after the nth pass, you can ignore the last n values.
actually, the situation is a bit better than that; you will often find runs of values which are already in sorted order. If you keep track of the highest index that actually got swapped, you don't need to go beyond that on your next pass.
So your sort function becomes
def bubblesort(items, *, key=None):
"""
Return items in sorted order
"""
# work on a copy of the list (don't destroy the original)
items = list(items)
# process key values - cache the result of key(item)
# so it doesn't have to be called repeatedly
keys = items if key is None else [key(item) for item in items]
# initialize the "last item to sort on the next pass" index
last_swap = len(items) - 1
# sort!
while last_swap:
ls = 0
for i in range(last_swap):
j = i + 1
if keys[i] > keys[j]:
# have to swap keys and items at the same time,
# because keys may be an alias for items
items[i], items[j], keys[i], keys[j] = items[j], items[i], keys[j], keys[i]
# made a swap - update the last_swap index
ls = i
last_swap = ls
return items
You may not be sure that this is actually correct, so let's test it:
from random import sample
def test_bubblesort(tries = 1000):
# example key function
key_fn = lambda item: (item[2], item[0], item[1])
for i in range(tries):
# create some sample data to sort
data = [sample("abcdefghijk", 3) for j in range(10)]
# no-key sort
assert bubblesort(data) == sorted(data), "Error: bubblesort({}) gives {}".format(data, bubblesort(data))
# keyed sort
assert bubblesort(data, key=key_fn) == sorted(data, key=key_fn), "Error: bubblesort({}, key) gives {}".format(data, bubblesort(data, key_fn))
test_bubblesort()
Now the rest of your code becomes
class Player:
def __init__(self, name, points, goals, gains):
self.name = name
self.points = points
self.goals = goals
self.gains = gains
players = [
Player("Henry", 0, 68, 6),
Player("Owen", 0, 52, 4),
Player("Drogba", 0, 46, 2)
]
# sort by goals
players = bubblesort(players, key = lambda player: player.goals)
# update points
for player in players:
player.points += player.gains
# show the result
for player in players:
print("{player.name:<10s} {player.points:>2d} pts".format(player=player))
which produces
Drogba 2 pts
Owen 4 pts
Henry 6 pts