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

#python

Вопрос:

У меня есть этот файл данных, и я должен найти 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. Мне они не кажутся целыми числами.

2. Вы должны инициализировать значения с float('-inf') помощью . В противном случае вы можете столкнуться с проблемами, когда в один прекрасный день наибольшее значение будет отрицательным.

Ответ №1:

Ваши данные 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]
 

Комментарии:

1. heapq.nlargest более эффективен для большого списка.

2. @eph На самом деле это не большой список, 144 items

Ответ №2:

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

Сортировка данных и выбор первых 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)
 

Комментарии:

1. Да, так лучше. 1 🙂

Ответ №3:

Ваше 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()

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

     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 совпадает с одним из самых больших значений. В таком случае 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 крайних случаев и.

Комментарии:

1. это возвращает (8.2, 73.0, 72.7) по какой-то причине в основном для i в темпах: это разделение данных по столбцам, но оно не проверяет все

2. В данный момент вы сравниваете строки. Вы должны преобразовать i в поплавок

3. как бы я это сделал, если я использую [float(i) для i в темпах]: это отбрасывает все

4. что вы подразумеваете под «отбрасыванием всего»? Пример кода см. в моем обновленном ответе.

5. ну, возврат-это просто распечатка (0,0,0), а не желание выложить, я не уверен, что происходит не так, я попробую запустить его через визуализатор

Ответ №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. ]