#python #sorting #datetime
#python #сортировка #дата-время
Вопрос:
Учитывая строку, содержащую формат datetime, я хочу сообщить пользователю, можно ли ее сортировать как string или нет.
Например:
'%Y-%m-%d %H:%M:%S'
сортируется'%m-%d %H:%M'
сортируется'%d-%m %H:%M'
нет (28-05 появится перед 29-04, если мы отсортируем его в строке)
Мой подход состоял бы в том, чтобы проанализировать строку и проверить, следуем ли мы следующему порядку:
- Y перед m перед d
- H перед M перед S
Этот подход утомителен, есть ли простой эффективный способ добиться этого?
Комментарии:
1. Вы можете использовать предоставленную строку формата для преобразования небольшого предварительно обработанного набора данных строк в
datetime
s и проверить, соответствует ли последовательность результата ожидаемой. Это также подтвердило бы предоставленную строку формата, которую, как известно, ошибаются даже опытные программисты.2. «‘%m-%d %H:%M’ сортируется» при условии, что все они относятся к одному году.
3. @tobias_k и в том же часовом поясе.
Ответ №1:
Ключ выбирает только те маркеры, которые присутствуют, а затем проверяет, находятся ли они в правильном порядке:
def is_sortable(format_string):
markers = ['%Y', '%m', '%d', '%H', '%M', '%s']
indices = [format_string.index(marker) for marker in markers if marker in format_string]
return indices == sorted(indices)
Если индексы расположены не в правильном порядке, строка не подлежит сортировке.
is_sortable('%Y-%m-%d %H:%M:%S')
True
is_sortable('%d-%m')
False
Приветствия
Ответ №2:
Чтобы выполнить проверку в линейное время, вы можете создать итератор из последовательности токенов форматирования, чтобы вы могли проверить порядок заданной строки форматирования, перебрав соответствующие токены в строке форматирования, чтобы найти следующее совпадение из итератора с помощью in
оператора:
def is_sortable(format, order='YmdHMS'):
tokens = set(order)
seq = iter(order)
return all(char in seq for char in format if char in tokens)
print(is_sortable('%Y-%m-%d %H:%M:%S')) # True
print(is_sortable('%m-%d %H:%M')) # True
print(is_sortable('%d-%m %H:%M')) # False
Ответ №3:
Я бы сделал это следующим образом:
import re
order = 'YmdHMS'
f1 = '%Y-%m-%d %H:%M:%S'
f2 = '%m-%d %H:%M'
f3 = '%d-%m %H:%M'
def is_sortable(x):
elems = re.findall(r'%(w)', x)
return elems == sorted(elems, key=order.index)
print(is_sortable(f1)) # True
print(is_sortable(f2)) # True
print(is_sortable(f3)) # False
Объяснение: я использую регулярное выражение для извлечения спецификатора из строки формата, затем сравниваю, сохраняют ли они порядок при sorted
использовании их позиции в order
as key
. order
строка, в которой ближний к концу меньший блок, следовательно, ниже .index
, указывает на больший блок и, таким образом, используя sorted
с key=order.index
, дает используемые единицы от наибольшего до наименьшего. Имейте в виду, что это решение завершится неудачей, если используется спецификатор, который отсутствует в order
.
Комментарии:
1. Ваша функция завершится с ошибкой, если какая-либо буква включена в формат, но не является частью маркера. Например, формат ISO
%Y-%m-%dT%H:%M:%s