简体   繁体   中英

How can I improve this messy function or its reiteration?

Very long and annoying question, ill try to do my best to explain it.

I have a file containing data such as

Sarah;Brown;s.brown@gmail.com;0715123451;1;24;0;0
Joe;Blogg;j.bloggs@gmail.com;0749814574;1;60;0;0
Andrew;Smith;a.smith@gmail.com;0718451658;1;45;0;0
Ray;Charles;r.charles@gmail.com;0715451589;1;40;0;0
Kevin;White;k.white@gmail.com;0749858748;1;20;0;0
Samantha;Collins;s.collins@gmail.com;0715243568;1;10;0;0
Frank;Jones;f.jones@gmail.com;0719487516;2;10;0;0
Liam;Blair;l.blair@gmail.com;0729857614;2;4;0;0
Pat;Phillips;p.phillips@gmail.com;071574216;2;17;0;0
John;Brown;j.brown@gmail.com;0798452648;2;11;0;0
Peter;Bond;p.bond@gmail.com;0798415758;6;4;0;0
Edward;Costello;e.costello@gmail.com;0712474588;2;45;0;0
Iain;Wilkins;i.wilkins@gmail.com;0715497211;2;23;0;0
Time;Pratchett;t.pratchett@gmail.com;0784975135;3;48;0;0
Eleanor;House;e.house@gmail.com;0799871542;3;9;0;0
Gergory;Davies;g.davies@gmail.com;0719475847;3;22;0;0
Tina;Turner;t.turner@gmail.com;0749857123;3;17;0;0
Sally;Stevens;s.stevens@gmail.com;077154198;3;30;0;0
John;Lennon;j.lennon@gmail.com;0704910874;3;29;0;0

The first element is the name, second is surname, third is email address, 4rth is phone number, 5th is division number, 6th is points scored, the remaining two don't matter for this issue.

What I have been asked to do is to check the top two scorers (6ths element) and the bottom two scorers in a division (5th element). When they have been identified, the top two should be promoted (go up a division), the bottom 2 should be demoted (go down a division). I have written this piece of crap:

def rollDivision2():

    lst = [line.strip().split(';') for line in open('players.txt','r').readlines()] # creates nested list
    totalPoints = []

    for i in range(len(lst)):
        if lst[i][4] == "2": # checking divisions this is why i need 6 different function
            totalPoints.append(int(lst[i][5])) # creates lists from all scores for the division chosen

#----------------------------------------------- figuring out best two scores and writing
    maxPoints = max(totalPoints)    
    for person in lst:
        if person[4] == "2" and person[5] == str(maxPoints): #this is why i need 6 different function
            biggest = person # creating variable with name of person that has the biggest score
            biggestStr = biggest[0] + ";" + biggest[1] + ";" + biggest[2] + ";" + biggest[3] + ";" + biggest[4] + ";" + biggest[5] + ";"  + biggest[6] + ";" + biggest[7] + "\n" #puts that lists into a string
            break #personWithMostPoints is the whole line of player with most points

    secondMaxPoints = secondLargest(totalPoints) #this is why i need 6 different function
    for person in lst:
        if person[4] == "2" and person[5] == str(secondMaxPoints): #checking for most points in the division
            secondBiggest = person
            secondBiggestStr = secondBiggest[0] + ";" + secondBiggest[1] + ";" + secondBiggest[2] + ";" + secondBiggest[3] + ";" + secondBiggest[4] + ";" + secondBiggest[5] + ";"  + secondBiggest[6] + ";" + secondBiggest[7] + "\n"
            break 

    lineToWriteBiggest = biggest[0] + ";" + biggest[1] + ";" + biggest[2] + ";" + biggest[3] + ";" + "1" + ";" + biggest[5] + ";"  + biggest[6] + ";" + biggest[7] + "\n"
    lineToWriteSecondBiggest = secondBiggest[0] + ";" + secondBiggest[1] + ";" + secondBiggest[2] + ";" + secondBiggest[3] + ";" + "1" + ";" + secondBiggest[5] + ";"  + secondBiggest[6] + ";" + secondBiggest[7] + "\n"
#----------------------------------------------- figuring out best two scores

#----------------------------------------------- figuring out worst two scores
    minPoints = min(totalPoints)    
    for person in lst:
        if person[4] == "2" and person[5] == str(minPoints): #this is why i need 6 different function
            least = person
            leastStr = least[0] + ";" + least[1] + ";" + least[2] + ";" + least[3] + ";" + least[4] + ";" + least[5] + ";"  + least[6] + ";" + least[7] + "\n"
            break #personWithMostPoints is the whole line of player with most points


    secondLeastPoints = secondSmallest(totalPoints) #method defined in utility functions   
    for person in lst:
        if person[4] == "2" and person[5] == str(secondLeastPoints): #this is why i need 6 different function
            secondLeast = person 
            secondLeastStr = secondLeast[0] + ";" + secondLeast[1] + ";" + secondLeast[2] + ";" + secondLeast[3] + ";" + secondLeast[4] + ";" + secondLeast[5] + ";"  + secondLeast[6] + ";" + secondLeast[7] + "\n"
            break 

    lineToWriteLeast = least[0] + ";" + least[1] + ";" + least[2] + ";" + least[3] + ";" + "3" + ";" + least[5] + ";"  + least[6] + ";" + least[7] + "\n"
    lineToWriteSecondLeast = secondLeast[0] + ";" + secondLeast[1] + ";" + secondLeast[2] + ";" + secondLeast[3] + ";" + "3" + ";" + secondLeast[5] + ";"  + secondLeast[6] + ";" + secondLeast[7] + "\n"




    f = open("players.txt","a")
    f.write(lineToWriteBiggest)
    f.write(lineToWriteSecondBiggest)
    f.write(lineToWriteLeast)
    f.write(lineToWriteSecondLeast)
    f.close()

    f = open("players.txt",'r') # Input file
    t = open("temp.txt", 'w') #Temp output file

    for line in f:
        if line != biggestStr and line != secondBiggestStr and line != leastStr and line != secondLeastStr and line != "\n":
            t.write(line) #writes all lines apart from the original line (one that needs to be deleted)

    f.close()
    t.close()
    os.remove("players.txt") #deletes players
    os.rename('temp.txt', 'players.txt') #new file with modified info is renamed to players

It is very ugly and impractical, moreover, I have to have 6 of these functions (as there are 6 divisions) which makes the program ridiculously overweight. If anyone could help me, whether it be how I could use this function just once to check all 6 division instead of having to write 6 individual ones.

I'm sorry you had to see this, I just don't know what else to do at this point. Any help would be very appreciated. Many thanks

lines = list(open("some.txt"))
for division,items in itertools.groupby(lines,lambda line:int(line.split(";")[4])):
    sorted_people = sorted(items,key=lambda item:int(item.split(";")[-1])
    print "DIVISION:",division
    print "TOP TWO:",sorted_people[-2:]
    print "BOTTOM TWO:",sorted_people[:2]

Check this out -

def convert(arr):
    return [int(x) if x.isnumeric() else x for x in arr]


def find_top_two(division):
    cur_div = [x for x in arr if x[4] == division]
    cur_div.sort(key = lambda T : T[5], reverse = True)
    return cur_div[:2]


def find_bottom_two(division):
    cur_div = [x for x in arr if x[4] == division]
    cur_div.sort(key = lambda T : T[5])
    return cur_div[:2]

with open('players.txt', 'r') as f:
    arr = f.readlines()

arr = [convert(s.strip('\n').split(';')) for s in arr]

print('Top 2 of division 2 :\n', find_top_two(2))

print('Bottom 2 of division 2 :\n', find_bottom_two(2))

Output -

Top 2 of division 2 :
 [['Edward', 'Costello', 'e.costello@gmail.com', 712474588, 2, 45, 0, 0], ['Iain', 'Wilkins', 'i.wilkins@gmail.com', 715497211, 2, 23, 0, 0]]
Bottom 2 of division 2 :
 [['Liam', 'Blair', 'l.blair@gmail.com', 729857614, 2, 4, 0, 0], ['Frank', 'Jones', 'f.jones@gmail.com', 719487516, 2, 10, 0, 0]]

Not the best and most efficient code, but this should work. I'll leave you to fill in the blanks.

def getPlayersOfDivision(playerInfo, division):
    result = []
    for player in playerInfo:
        if int(player[4]) == division:
            result.append(player)

def findPlayer(playerInfo, firstName, lastName):
    for i,player in enuemrate(playerInfo):
        if player[0] == firstName and player[1] = lastName:
            return i

def get2BestPlayers(playerInfo):
    pass

def get2WorstPlayers(playerInfo):
    pass

def changePlayerDivision(playerInfo, pos, upOrDown):
    pass

with open('players.txt', 'r') as f:
    playerInfo = f.readlines()

playerInfo = [line.strip().split(';') for line in playerInfo]

numDivisions = ???
for i in range(numDivisions):
    divisionPlayers = getPlayersOfDivision(playerInfo, i)
    bestPlayers = get2BestPlayers(divisionPlayers)
    worstPlayers = get2WorstPlayers(divisionPlayers)
    newPlayerInfo = changePlayerDivision(playerInfo, findPlayer(playerInfo, divisionPlayer[bestPlayers[0]][0], divisionPlayer[bestPlayers[0]][1]), +1)
    newPlayerInfo = changePlayerDivision(playerInfo, findPlayer(playerInfo, divisionPlayer[bestPlayers[1]][0], divisionPlayer[bestPlayers[1]][1]), +1)
    newPlayerInfo = changePlayerDivision(playerInfo, findPlayer(playerInfo, divisionPlayer[worstPlayers[0]][0], divisionPlayer[worstPlayers[0]][1]), -1)
    newPlayerInfo = changePlayerDivision(playerInfo, findPlayer(playerInfo, divisionPlayer[worstPlayers[1]][0], divisionPlayer[worstPlayers[1]][1]), -1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM