преобразование вложенного l oop в лучший формат - PullRequest
0 голосов
/ 04 марта 2020

Я написал следующий код, который просматривает CSV-файл и проверяет, выполнил ли пользователь два действия менее чем за 10 секунд:

import csv
import datetime
import dateutil.parser
import sys

csvFileName = 'edited.csv'




with open(csvFileName, 'r') as csvFile:
        csvReader = csv.DictReader(csvFile)

        for index, row in enumerate(csvReader):
            userIdentity = row['useridentity']
            eventTime = dateutil.parser.parse(row['eventtime'])
            for subIndex, subRow in enumerate(csvReader):
                subUserIdentity = subRow['useridentity']
                subEventTime = dateutil.parser.parse(subRow['eventtime'])
                if subIndex - index == 1  and userIdentity == subUserIdentity:
                    if subEventTime - eventTime < datetime.timedelta(seconds=10):
                        print('heads up!')
                        print(eventTime)
                        print(subEventTime)

'eventtime' содержит время в формате iso 8601, которое преобразован в объект datetime. Есть 2 проблемы:

  1. Вложенность означает, что он запускается над файлом ^ 2 раза

  2. В этом формате, если я хочу чтобы изменить его для сравнения с 3-мя действиями вместо 2-х, ему понадобится другое вложенное значение для l oop

Я бы хотел понять, что является лучшим и правильным способом написать что-то подобное.

Обновите это моя обновленная попытка, но результаты дублируются:

import csv
import datetime
import dateutil.parser
import sys

csvFileName = 'edited.csv'

def seqCounter(index, currentTime):
    tmpIndex = 0
    with open(csvFileName, 'r') as tmpFile:
        tmpReader = csv.DictReader(tmpFile)
        for row in tmpReader:
            if tmpIndex <= index:
                tmpIndex += 1
                continue
            eventTime = dateutil.parser.parse(row['eventtime'])
            if eventTime - currentTime < datetime.timedelta(seconds=2) and eventTime - currentTime > datetime.timedelta(seconds=0):
                print('heads up')
                print(row['useridentity'])
                print(eventTime)
                print(currentTime)



with open(csvFileName, 'r') as csvFile:
        csvReader = csv.DictReader(csvFile)

        for index, row in enumerate(csvReader):
            currentTime = dateutil.parser.parse(row['eventtime'])
            seqCounter(index, currentTime)

1 Ответ

2 голосов
/ 04 марта 2020

Это будет работать, если вы проверяете предыдущее событие только тем же пользователем. Вместо повторения цикла по всему файлу для каждой записи, это будет хранить последнее событие того же пользователя в dict. Это позволяет l oop пройти весь файл ровно один раз.

with open(csvFileName, 'r') as csvFile:
        csvReader = csv.DictReader(csvFile)
        user_events = dict()
        for index, row in enumerate(csvReader):
            userIdentity = row['useridentity']
            eventTime = dateutil.parser.parse(row['eventtime'])

            # Get the last event for this user 
            lastEventTime = user_events.get(userIdentity)
            if lastEventTime:
                if lastEventTime - eventTime < datetime.timedelta(seconds=10):
                    print('heads up!')
                    print(eventTime)
                    print(lastEventTime)

            # Set the one we just looked at as the last event
            user_events[userIdentity] = eventTime
...