Finding the top 10 and converting it from centimeters to inches - Python
Question: I am reading data from file, like listed below, it is a .dat file:

    
    
    1
    Carmella Henderson
    24.52
    13.5
    21.76
    2
    Christal Piper
    14.98
    11.01
    21.75
    3
    Erma Park
    12.11
    13.51
    18.18
    4
    Dorita Griffin
    20.05
    10.39
    21.35
    

The file itself contains 50 records. From this data I need the person number,
name and the first number, like so:

    
    
    1 #person number
    Marlon Holmes  #Name
    18.86 # First number
    13.02 # Second Number
    13.36 # Third Number
    

I already have code to read the data however I unable to get the top 10
results based on the #First number

The #First number in the Top 10 currently is in centimeters but needs to be
converted to inches, I am unsure on how to combine the top 10 and conversion
into one alongside the reading of the data

Code that reads the data:

    
    
     with open('veggies_2016.txt', 'r') as f:
            count = 0
            excess_count = 0
            for line in f:
                if count < 3:
                    print(line)
                    count += 1
                elif count == 3 and excess_count < 1:
                    excess_count += 1
                else:
                    count = 0
                    excess_count = 0
    

As mentioned the code reads the file, like so #Person number, #name and #first
number, but #first number needs to be converted to inches and then all of the
data needs to be sorted to find the top 10

This process will also have to be repeated for #second number and #third
number however they are separate in terms of their code from #first number

I have tried to read the data then append to a list and sort it and convert it
from that but with no success, any help would be appreciated

Whole code:

    
    
    from collections import OrderedDict
    from operator import itemgetter
    import pprint
    def menu():
        exit = False
    
    
        while not exit:
            print("To enter new competitior data, type new")
            print("To view the competition score boards, type Scoreboard")
            print("To view the Best Overall Growers Scoreboard, type Podium")
            print("To review this years and previous data, type Data review")
            print("Type quit to exit the program")
    
            choice = raw_input("Which option would you like?")
    
            if choice == 'new':
                new_competitor()
            elif choice == 'Scoreboard':
                scoreboard_menu()
            elif choice == 'Podium':
                podium_place()
            elif choice == 'Data review':
                data_review()
            elif choice == 'quit':
                print("Goodbye")
                raise SystemExit
    
    """Entering new competitor data: record competitor's name and vegtables lengths"""
    
    def competitor_data():
        global competitor_num
        l = []
    
        print("How many competitors would you like to enter?")
    
        competitors = raw_input("Number of competitors:")
    
        num_competitors = int(competitors)
    
        for i in range(num_competitors):
    
            name = raw_input("Enter competitor name:")
            Cucumber = raw_input("Enter length of Cucumber:")
            Carrot = raw_input("Enter length of Carrot:")
            Runner_Beans = raw_input("Enter length of Runner Beans:")
    
            l.append(competitor_num)
            l.append(name)
            l.append(Cucumber)
            l.append(Carrot)
            l.append(Runner_Beans)
    
            competitor_num += 1
    
        return (l)
    def new_competitor():
        with open('veggies_2016.txt', 'a') as f:
            for item in competitor_data():
                f.write("%s\n" %(item))
    def scoreboard_menu():
        exit = False
    
        print("Which vegetable would you like the scoreboard for?")
    
        vegetable = raw_input("Please type either Cucumber, Carrot or Runner Beans:")
    
        if vegetable == "Cucumber":
            Cucumber_Scoreboard()
        elif vegetable == "Carrot":
            Carrot_Scoreboard()
        elif vegetable == "Runner Beans":
            Runner_Beans_Scoreboard()
    
    def Cucumber_Scoreboard():
        exit = True
    
        print("Which year would you like the Scoreboard from?")
    
        scoreboard = raw_input("Please type a year:")
    
        if scoreboard == "2015":
            cucumber_veg_2015()
        elif scoreboard == "2014":
            cucumber_veg_2014()
        elif scoreboard == "2016":
            cucumber_veg_2016()
    
    
    def cucumber_veg_2016(cm):
        return float(cm) / 2.54
    
    names = OrderedDict([('Competitor Number', int),
                         ('Competitor Name', str),
                         ('Cucumber', cucumber_veg_2016),
                         ('Carrot', float),
                         ('Runner Bean', float)])
    data = []
    with open('veggies_2016.txt') as fobj:
        while True:
            item = {}
            try:
                for name, func in names.items():
                    item[name] = func(next(fobj).strip())
                data.append(item)
            except StopIteration:
                break
    
    pprint.pprint(sorted(data, key=itemgetter('Cucumber'))[:10])
    


Answer: # Solution

Reading the data into a list of dictionaries would work:

    
    
    from collections import OrderedDict
    from operator import itemgetter
    import pprint
    
    def to_inch(cm):
        return float(cm) / 2.54
    
    names = OrderedDict([('person_number', int),
                         ('name', str),
                         ('first', to_inch),
                         ('second', float),
                         ('third', float)])
    data = []
    with open('veggies_2016.txt') as fobj:
        while True:
            item = {}
            try:
                for name, func in names.items():
                    item[name] = func(next(fobj).strip())
                data.append(item)
            except StopIteration:
                break
    
    pprint.pprint(sorted(data, key=itemgetter('first'))[:10])
    

Output:

    
    
    [{'first': 4.76771653543307,
      'name': 'Erma Park',
      'person_number': 3,
      'second': 13.51,
      'third': 18.18},
     {'first': 5.897637795275591,
      'name': 'Christal Piper',
      'person_number': 2,
      'second': 11.01,
      'third': 21.75},
     {'first': 7.893700787401575,
      'name': 'Dorita Griffin',
      'person_number': 4,
      'second': 10.39,
      'third': 21.35},
     {'first': 9.653543307086613,
      'name': 'Carmella Henderson',
      'person_number': 1,
      'second': 13.5,
      'third': 21.76}]
    

# In Steps

This helper function converts centimeters into inches:

    
    
    def to_inch(cm):
        return float(cm) / 2.54
    

We use an ordered dictionary to hold the names for the different items we want
to read in order. The value is a function that we use to convert the read
value for each item:

    
    
    names = OrderedDict([('person_number', int),
                         ('name', str),
                         ('first', to_inch),
                         ('second', float),
                         ('third', float)])
    

We start with an empty list:

    
    
    data = []
    

And open our file:

    
    
    with open('veggies_2016.txt') as fobj:
    

We do something without a defined end and create a new dictionary `item` each
time:

    
    
        while True:
            item = {}
    

We try to read from the file until it is finished, i.e. until we get a
`StopIteration` exception:

    
    
            try:
                for name, func in names.items():
                    item[name] = func(next(fobj).strip())
                data.append(item)
            except StopIteration:
                break
    

We go through the keys and values of our order dictionary `names` and call
each value, i.e. the function `func()` on the next line we retrieve with
`next()`. This converts the entry into the desired datatype and does the cm-
inch conversion for `first`. After reading all items for one person, we append
the dictionary to the list `data`.

Finally, we sort by the key `first` and print out the 10 to entries (my
example file has less than 10 entries):

    
    
    pprint.pprint(sorted(data, key=itemgetter('first'))[:10])
    

# Integration with your code:

You need to put the code into the function `podium_place()`:

    
    
    def cucumber_veg_2016(cm):
        return float(cm) / 2.54
    
    def podium_place():
        names = OrderedDict([('Competitor Number', int),
                             ('Competitor Name', str),
                             ('Cucumber', cucumber_veg_2016),
                             ('Carrot', float),
                             ('Runner Bean', float)])
        data = []
        with open('veggies_2016.txt') as fobj:
            while True:
                item = OrderedDict()
                try:
                    for name, func in names.items():
                        item[name] = func(next(fobj).strip())
                    data.append(item)
                except StopIteration:
                    break
    
        sorted_data = sorted(data, key=itemgetter('Cucumber'), reverse=True)
        for entry in sorted_data[:10]:
            for key, value in entry.items():
                print key, value
            print
    
    menu()
    

At the end you need to call `menu()`. Also, if top mean largest first, you
need sort `reverse` (see above).

