Вставка строки со временем в отсортированный список времен фиксированной длины

#python #list

#python #Список

Вопрос:

У меня есть фрагмент кода, как показано ниже, где, если время меньше значения в списке 5 раз, я хочу вставить новое значение в список и удалить 5-е значение в списке, по существу обновляя список новым набором из пяти лучших раз.

 hours=str(input('enter hours:'))
minutes=int(input('enter minutes:'))
seconds=int(input('enter seconds:'))

if minutes <10:
    minutes='0' str(minutes)
if seconds <10:
    seconds='0' str(seconds)
    
currentTime=hours ':' str(minutes) ':' str(seconds)
print(currentTime)
hours=int(currentTime[0])
minutes=int(currentTime[2] currentTime[3])
seconds=int(currentTime[5] currentTime[6])
print(hours, minutes, seconds)

for i in range(1,6):
    aTime=str(Times[0][i])
    print(Times[0][i])
    if hours==int(aTime[1]):
        if minutes==int(aTime[3] aTime[4]):
            if seconds <=int(aTime[6] aTime[7]):
                #equal values deemed quicker
                print('quicker time than time',str(i))
                #insert value in Times[0][i]
                break
        elif minutes<int(aTime[3] aTime[4]):
            print('quicker time than time',str(i))
            #insert value in Times[0][i]
            break
    elif hours<int(aTime[1]):
        print('quicker time than time',str(i))
        #insert value in Times[0][i]
        break
 

Пример того, чего я хочу добиться, если;

 Times=['1:30:00','2:00:00','2:00:00','2:00:00','2:00:00']
 

и, например, текущий Time='1:45:00'

Это время должно стать:

 Times=['1:30:00','1:45:00','2:00:00','2:00:00','2:00:00']
 

Похоже, что этот вопрос задавался раньше, но не мог его найти.
Заранее спасибо.

Примечание: я полагаю, что это, вероятно, очень неэффективный способ сравнения времен, но метод правильный, просто нужно знать, как вставить значение в список по существу.

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

1.хммм, добавление нужных элементов в список mylist выполняется с mylist.append(item) добавлением их в определенную позицию в этом списке выполняется с mylist.insert(position,item) docs.python.org/3/library /…

2. и замена элемента в заданной позиции выполняется mylist[position] = item

3. Не проще ли добавить в конце, а затем просто отсортировать список снова?

Ответ №1:

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

Мы будем называть это MaxList так как:

  • Он сохраняет только минимальные элементы
  • В нем максимальное количество элементов
 class MaxList:
    
    def __init__(self, size, remaining=None):
        self._size = size
        self._contents = []
        if remaining:
            self._contents = remaining

    def append(self, item):
        for i, entry in enumerate(self._contents):
            if item < entry:
                self._contents.insert(i, item)
                break
        self._contents = self._contents[:self._size]

    def __repr__(self):
        return self._contents.__repr__()
 

Эта реализация предполагает, что список начинает сортироваться, и работает следующим образом:

 >>> ls = MaxList(5, [1, 3, 5, 7, 9])  # 5 is the total length, rest is the list
>>> ls
[1, 3, 5, 7, 9]
>>> ls.append(8)
>>> ls
[1, 3, 5, 7, 8]    # `9` was pushed out
>>> ls.append(10)
>>> ls
[1, 3, 5, 7, 8]    # Notice `10` is not in the list
>>> ls.append(-1)
>>> ls
[-1, 1, 3, 5, 7]
>>> ls.append(-5)
>>> ls
[-5, -1, 1, 3, 5]
 

Я бы рекомендовал использовать нестроковое представление для времени: это упростит сравнение и решит, является ли одно значение меньше или больше другого. datetime Объекты в стандартной библиотеке Python могут быть хорошим местом для начала.

Например:

 from datetime import time

times = MaxList(5, [
    time(1, 30, 0),
    time(2, 0, 0),
    time(2, 0, 0),
    time(2, 0, 0),
    time(2, 0, 0),
])

print(times)

times.append(time(1, 45, 0))

print(times)
 

Вывод:

 [datetime.time(1, 30), datetime.time(2, 0), datetime.time(2, 0), datetime.time(2, 0), datetime.time(2, 0)]
[datetime.time(1, 30), datetime.time(1, 45), datetime.time(2, 0), datetime.time(2, 0), datetime.time(2, 0)]
 

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

1. Вы также можете использовать heapq модуль здесь… Если для OP возможно реорганизовать свой цикл ввода в качестве функции генератора и выдавать каждое значение, тогда вызов heapq.nsmallest(5, input_function()) будет работать хорошо

Ответ №2:

 timeint = int(newtime.replace(':', ''))
for n, i in enumerate(list):
    i = int(i.replace(':', ''))
    if i > timeint:
        list[n] = newtime
        break
print(list)
 

где newtime — это новое время, которое вы пытаетесь сравнить, а list — список предыдущих времен

Ответ №3:

Для этого вы можете использовать модуль bisect .

 import bisect 

Times=['1:30:00','2:00:00','2:00:00','2:00:00','2:00:00']

Time='1:45:00'

Times[bisect.bisect(Times, Time)]=Time 

>>> Times
['1:30:00', '1:45:00', '2:00:00', '2:00:00', '2:00:00']
 

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

См. ISO 8601. Строки только для времени — это подмножество, которое можно обрабатывать одинаково.

Хотя строки будут работать, лучший способ хранения и сравнения времени и дат в Python — это модуль datetime . Вы можете использовать модуль bisect с объектами datetime для вставки в отсортированный список таким же образом.