Ошибка в функции для возврата 3 самых больших значений из списка чисел

У меня есть этот файл данных, и мне нужно найти 3 больших числа, которые он содержит

24.7    25.7    30.6    47.5    62.9    68.5    73.7    67.9    61.1    48.5    39.6    20.0
16.1    19.1    24.2    45.4    61.3    66.5    72.1    68.4    60.2    50.9    37.4    31.1
10.4    21.6    37.4    44.7    53.2    68.0    73.7    68.2    60.7    50.2    37.2    24.6
21.5    14.7    35.0    48.3    54.0    68.2    69.6    65.7    60.8    49.1    33.2    26.0
19.1    20.6    40.2    50.0    55.3    67.7    70.7    70.3    60.6    50.7    35.8    20.7
14.0    24.1    29.4    46.6    58.6    62.2    72.1    71.7    61.9    47.6    34.2    20.4
8.4     19.0    31.4    48.7    61.6    68.1    72.2    70.6    62.5    52.7    36.7    23.8
11.2    20.0    29.6    47.7    55.8    73.2    68.0    67.1    64.9    57.1    37.6    27.7
13.4    17.2    30.8    43.7    62.3    66.4    70.2    71.6    62.1    46.0    32.7    17.3
22.5    25.7    42.3    45.2    55.5    68.9    72.3    72.3    62.5    55.6    38.0    20.4
17.6    20.5    34.2    49.2    54.8    63.8    74.0    67.1    57.7    50.8    36.8    25.5
20.4    19.6    24.6    41.3    61.8    68.5    72.0    71.1    57.3    52.5    40.6    26.2

Поэтому я написал следующий код, но он ищет только первую строку чисел, а не весь список. Может ли кто-нибудь помочь найти ошибку?

def three_highest_temps(f):
    file = open(f, "r")
    largest = 0
    second_largest = 0
    third_largest = 0
    temp = []
    for line in file:
        temps = line.split()

        for i in temps:
            if i > largest:
                largest = i
            elif largest > i > second_largest:
                second_largest = i
            elif second_largest > i > third_largest:
                third_largest = i
        return largest, second_largest, third_largest

print(three_highest_temps("data5.txt"))

Ответы

Ответ 1

Ваш оператор return находится внутри цикла for. Как только возвращение достигнуто, функция завершается, поэтому цикл никогда не попадает во вторую итерацию. Переместите return за пределы цикла, уменьшив отступ.

    for line in file:
        temps = line.split()

        for i in temps:
            if i > largest:
                largest = i
            elif largest > i > second_largest:
                second_largest = i
            elif second_largest > i > third_largest:
                third_largest = i
    return largest, second_largest, third_largest

Кроме того, ваши сравнения не будут работать, потому что line.split() возвращает список строк, а не плавает. (Как уже указывалось, ваши данные состоят из float, а не ints. Я предполагаю, что задача состоит в том, чтобы найти самый большой float.) Итак, пусть преобразовать строки, используя float()

Ваш код все равно будет неправильным, потому что, когда вы находите новое самое большое значение, вы полностью отказываетесь от старого. Вместо этого вы должны теперь рассмотреть это второе по величине известное значение. То же правило применяется для второго и третьего по величине.

    for line in file:
        temps = line.split()

        for temp_string in temps:
            i = float(temp_string)
            if i > largest:
                third_largest = second_largest
                second_largest = largest
                largest = i
            elif largest > i > second_largest:
                third_largest = second_largest
                second_largest = i
            elif second_largest > i > third_largest:
                third_largest = i
    return largest, second_largest, third_largest

Теперь есть одна последняя проблема:

Вы пропускаете случаи, когда я совпадает с одним из самых больших значений. В таком случае i > largest будет ложным, но так будет largest > i. Вы можете изменить любое из этих сравнений на >=, чтобы исправить это.

Вместо этого упростим предложения if, считая, что условия elif рассматриваются только после того, как все предыдущие условия уже были признаны ложными. Когда мы достигаем первого elif, мы уже знаем, что i не может быть больше, чем largest, поэтому достаточно сравнить его с second largest. То же самое касается второго elif.

    for line in file:
        temps = line.split()

        for temp_string in temps:
            i = float(temp_string)
            if i > largest:
                third_largest = second_largest
                second_largest = largest
                largest = i
            elif i > second_largest:
                third_largest = second_largest
                second_largest = i
            elif i > third_largest:
                third_largest = i
    return largest, second_largest, third_largest

Таким образом, мы избегаем случайного отфильтровывания краевых случаев i == largest и i == second_largest.

Ответ 2

Ваши данные содержат float номера не integer.

Вы можете использовать sorted:

>>> data = '''24.7    25.7    30.6    47.5    62.9    68.5    73.7    67.9    61.1    48.5    39.6    20.0
... 16.1    19.1    24.2    45.4    61.3    66.5    72.1    68.4    60.2    50.9    37.4    31.1
... 10.4    21.6    37.4    44.7    53.2    68.0    73.7    68.2    60.7    50.2    37.2    24.6
... 21.5    14.7    35.0    48.3    54.0    68.2    69.6    65.7    60.8    49.1    33.2    26.0
... 19.1    20.6    40.2    50.0    55.3    67.7    70.7    70.3    60.6    50.7    35.8    20.7
... 14.0    24.1    29.4    46.6    58.6    62.2    72.1    71.7    61.9    47.6    34.2    20.4
... 8.4     19.0    31.4    48.7    61.6    68.1    72.2    70.6    62.5    52.7    36.7    23.8
... 11.2    20.0    29.6    47.7    55.8    73.2    68.0    67.1    64.9    57.1    37.6    27.7
... 13.4    17.2    30.8    43.7    62.3    66.4    70.2    71.6    62.1    46.0    32.7    17.3
... 22.5    25.7    42.3    45.2    55.5    68.9    72.3    72.3    62.5    55.6    38.0    20.4
... 17.6    20.5    34.2    49.2    54.8    63.8    74.0    67.1    57.7    50.8    36.8    25.5
... 20.4    19.6    24.6    41.3    61.8    68.5    72.0    71.1    57.3    52.5    40.6    26.2
... '''

>>> sorted(map(float, data.split()), reverse=True)[:3]
[74.0, 73.7, 73.7]

Если вы хотите integer результаты

>>> temps = sorted(map(float, data.split()), reverse=True)[:3]
>>> map(int, temps)
[74, 73, 73]

Ответ 3

Вы получаете только максимальные элементы для первой строки, потому что вы возвращаетесь в конце первой итерации. Вы должны отменить операцию возврата.

Сортировка данных и выбор первых трех элементов выполняется в n * log (n).

data = [float(v) for v in line.split() for line in file]
sorted(data, reverse=True)[:3]

Это отлично подходит для 144 элементов. Вы также можете получить ответ в линейном режиме, используя heapq

import heapq
heapq.nlargest(3, data)

Ответ 4

Так как вы имеете дело с файлом, как литой и numpythonic подход, вы можете загрузить файл в виде массива, а затем отсортировать массив и получить последние 3 элемента:

import numpy as np
with open('filename') as f:
    array = np.genfromtxt(f).ravel()
    array.sort()

print array[-3:]
[ 73.7  73.7  74. ]