#python #list #file #datetime
#python #Список #файл #дата и время
Вопрос:
У меня есть файл, и я хочу добавить несколько строк в пустой список, если они соответствуют 2 условиям:
- Я беру только те строки, в которых есть a
country_code
, который также присутствует вmy_countrycodes
И - для каждого
country_code
я беру МАКСИМАЛЬНУЮ дату-время, если эта дата-время <my_time1
Пожалуйста, обратите внимание, что country_code
каждая строка индексируется [1]
в файле, а дата-время каждой строки является переменной с именем date_time4
.
Это мой код:
my_time = '2020-09-06 16:00:45'
my_time1 = datetime.datetime.strptime(my_time, '%Y-%m-%d %H:%M:%S')
my_countrycodes = ['555', '256', '1000']
all_row_times = [] #<--- this is the list where we will append the datetime values of the file
new_list = [] #<--- this is the final list where we will append our results
with open(root, 'r') as out:
reader = csv.reader(out, delimiter = 't')
for row in reader:
# print(row)
date_time1 = row[-2] row[-1] #<--- concatenate date time
date_time2 = datetime.datetime.strptime(date_time1, '%d-%m-%Y%H:%M:%S') #<--- make a datetime object of the string
date_time3 = datetime.datetime.strftime(date_time2, '%Y-%m-%d %H:%M:%S') #<--- turn the datetime object back to a string
date_time4 = datetime.datetime.strptime(date_time3, '%Y-%m-%d %H:%M:%S') #<--- turn the string object back to a datetime object
all_row_times.append(date_time4) #<--- put all the datetime objects into a list.
if any(country_code in row[1] for country_code in my_countrycodes) and date_time4 == max(dt for dt in all_row_times if dt < my_time1):
new_list.append(row) #<-- append the rows with the same country_code in my_countrycodes and the latest time if that time is < my_time1
print(new_list)
Вот как выглядит файл:
введите описание изображения здесь
Это вывод new_list
:
[['USA', '555', 'White', 'True', 'NY', '06-09-2020', '10:11:32'],
['USA', '555', 'White', 'True', 'BS', '06-09-2020', '10:11:32'],
['EU', '256', 'Blue', 'False', 'BR', '06-09-2020', '11:26:21'],
['GE', '1000', 'Green', 'True', 'BE', '06-09-2020', '14:51:45'],
['GE', '1000', 'Green', 'True', 'BE', '06-09-2020', '15:59:45']]
Как вы можете видеть, код извлекает строки с country_codes
555
помощью , 256
и 1000
, он также принимает строки, которые меньше, чем < my_time1
. Итак, эта часть работает идеально. Однако строка 1000
имеет 2 разных даты и времени, и я не понимаю, почему она не принимает только максимальное время даты.
Это ожидаемый результат new_list
:
[['USA', '555', 'White', 'True', 'NY', '06-09-2020', '10:11:32'],
['USA', '555', 'White', 'True', 'BS', '06-09-2020', '10:11:32'],
['EU', '256', 'Blue', 'False', 'BR', '06-09-2020', '11:26:21'],
['GE', '1000', 'Green', 'True', 'BE', '06-09-2020', '15:59:45']]
Ответ №1:
На самом деле, требуется только МАКСИМАЛЬНОЕ значение даты и времени, но в цикле for на 14:51:45
первом месте. Ваш код сравнивает это с другими, и, поскольку другое значение еще не появилось, оно принимается за максимальное значение.
На следующей итерации появляется другой код страны, и, поскольку это время больше, чем у других, эта строка также добавляется. Я думаю, это то, чего вам не хватает.
Вы можете попробовать что-то вроде этого.
my_time = datetime.datetime.strptime('2020-09-06 16:00:45', '%Y-%m-%d %H:%M:%S')
my_countrycodes = ['555', '256', '1000']
country_code_max_date_rel = {}
matched_rows = []
with open(root, 'r') as out:
reader = csv.reader(out, delimiter = 't')
for row in reader:
date_time = datetime.datetime.strptime(row[-2] row[-1], '%d-%m-%Y%H:%M:%S')
if any(country_code in row[1] for country_code in my_countrycodes):
matched_rows.append(row)
try:
if country_code_max_date_rel[str(row[1])] < date_time:
raise KeyError
except KeyError:
country_code_max_date_rel[str(row[1])] = date_time
На данный момент у вас есть максимальное значение для каждой страны. А также список строк.
Если вы снова фильтруете, как;
new_list = []
for row in matched_rows:
country_code = row[1]
date_time = datetime.datetime.strptime(row[-2] row[-1], '%d-%m-%Y%H:%M:%S')
if date_time == country_code_max_date_rel[country_code]:
if date_time < my_time:
new_list.append(row)
Новый список:
[['USA', '555', 'White', 'True', 'NY', '06-09-2020', '10:11:32'],
['USA', '555', 'White', 'True', 'BS', '06-09-2020', '10:11:32'],
['EU', '256', 'Blue', 'False', 'BR', '06-09-2020', '11:26:21'],
['GE', '1000', 'Green', 'True', 'BE', '06-09-2020', '15:59:45']]
Этот код не очень хорош, но я думаю, он поможет вам обновить ваш.
Комментарии:
1. Спасибо, аби. Действительно отличный фрагмент кода. Вы не возражаете, если я расскажу вам в личке, что именно вы сделали?
2. Спасибо, брат, я проверю это.
3. Я не вижу
my_time
возврата в вашем коде? Что вы с этим сделали? Откуда ваш код знает, что он должен принимать только те строки, которые < thenmy_time
Ответ №2:
Извините, я не уверен, что вы пытаетесь здесь сделать. Предполагая, что вы хотите иметь только один экземпляр contrycode
в вашем new_list
с последним временем, прежде my_tim1
чем вот ответ:
Логика в вашем коде неверна. Прямо сейчас вы перебираете все строки из своего csv-файла и применяете то же условие перед добавлением новой строки new_list
.
В данном случае ['GE', '1000', 'Green', 'True', 'BE', '06-09-2020', '15:59:45']
добавляется, потому что условие 1 истинно (1000 находится в my_countrycodes), а условие 2 также истинно ( '06-09-2020', '15:59:45'
меньше, my_time1
и это также «самое большое» время new_list
).
Вы могли бы решить эту проблему разными способами, но вот несколько предложений:
-
Измените свое решение следующим образом:
проверьте, включено лиrow[1]
str(my_countrycodes)
,
проверьте, меньше ли время строкиmy_time1
Проверьте, указан ли код страны в строкеnew_list
,
если его нет,new_list
добавьте его,
если он есть,new_list
проверьте, соответствуют ли новые дата и время вашему условию, и если да, обновите столбец даты и времени для этой строки. -
Отфильтруйте ваш файл по кодам стран, а затем извлеките максимум из отфильтрованного результата для каждого кода страны
Будьте осторожны, какой у вас ключ, поскольку у вас есть countrycode
, который повторяется с разными параметрами. (‘NY’, ‘BS’)
Предложения и комментарии:
- Для быстрого доступа к данным вы можете использовать словари. Использование countrycode в качестве ключа предоставит вам легкий доступ к данным и поможет быстро проверить их существование и обновить его параметры.
any(country_code in row[1] for country_code in my_countrycodes)
может быть записан как:
row[1] in str(my_countrycodes)
или вы даже могли бы создатьmy_country_code_str = str(my_countrycodes)
перед вводом цикла for.- Я не знаю, почему вы перебрасываете дату и время назад, но поскольку вам нужен только последний, этого достаточно, чтобы сделать это:
rows_date_time = datetime.datetime.strptime(row[-2] row[-1], '%d-%m-%Y%H:%M:%S')
помните, что вы можете отформатировать его по своему усмотрению с помощью'%d-%m-%Y%H:%M:%S'
- Не забудьте дать своим переменным осмысленные имена и придерживаться одного стандарта кодирования в вашем коде (ig. когда вы используете подчеркивание, используйте его последовательно)