求一个关于日期时间间隔计算相关的算法,具体问题如下:
当前有一个比较大(上万个)日期时间的list(时间递增但无规律),假设 dt=[
'2015-01-02 10:21:02',
'2015-01-02 10:21:02'
'2015-01-02 10:21:03'
'2015-01-02 10:21:04'
'2015-01-02 10:21:06'
'2015-01-02 10:21:10'
'2015-01-02 10:21:11'
'2015-01-02 10:21:13'
'2015-01-02 10:22:00'
'2015-01-02 10:22:12'
... ...
]
给定一个时间间隔timeframe(假设4s),现在问题是:求在给定连续时间间隔内,list中最多项数目。
最简单的方法是依次对于list中每个项x,向后查找直至大于timeframe+x的项并统计个数。但由于这个list数量庞大,同时还要涉及时间运算,算法难以达到要求,特来请教!
Donnez-moi d'abord ma réponse :
N'oubliez pas d'importer
datetime
ettimedelta
pour le code ci-dessus.Il s'agit d'une approche O(n), n est le nombre de
timestrs
.Le code est un peu moche, je le corrigerai plus tard, mais afin de comparer la vitesse et l'exactitude, j'ai fait quelques expériences Voici le code complet que j'ai utilisé pour faire les expériences :
Contient
Un décorateur très cool pour le timing :
simpletimer
Il décorera
func
, en imprimant le temps qu'il a fallu pour exécuterUne fonction qui génère des résultats de tests aléatoires :
gentimestrs
Il générera
count
données de test de chaînes de temps, et l'intervalle de temps de chaque donnée est un entier aléatoire inférieur ou égal àdelta
Les
findmax
etfindmax2
suivants sont respectivement mon approche et celle de @citaret (si vous êtes intéressé, vous pouvez imiter l'interface et ajouter vos propres fonctions, et le questionneur peut également utiliser son approche originale) Comparons) et utilisonssimpletimer
pour chronométrer.Lors des tests, générez d'abord les actifs de test, puis exécutez les fonctions à comparer dans
funclst
L'exemple d'exécution est le suivant :
Voici quelques résultats :
Utilisez
timeframe==5
pour tester le montant des fonds 1000, 10000, 100000Utilisez
timeframe==10
pour tester le montant des fonds 1000, 10000, 100000Si la durée de la période reste inchangée, les deux périodes afficheront une croissance linéaire du nombre de fonds de test
Mais lorsque le délai double, la deuxième méthode prendra deux fois plus de temps
Cela signifie que la complexité maximale de la méthode de @citaret doit être O(n * timeframe)
Un autre point est que parfois les résultats de ces deux méthodes ne sont pas les mêmes, il y aura une différence si le questionneur a une méthode, il peut en vérifier l'exactitude
.La réponse que j'ai trouvée semble être correcte, mais veuillez me corriger si j'ai commis des erreurs. Merci !
Davantage de personnes sont invitées à discuter de cette question.
Questions auxquelles j'ai répondu : Python-QA
Il n'y a pas de données et pas de bon profil. Donnons d'abord une version pour voir si d'autres ont de meilleures solutions.
@dokelung l'a testé en utilisant l'algorithme citaret. Pour une liste avec un total de 27 505 éléments (extraits d'un seul fichier journal de 630 000 lignes et agrégés à partir de plusieurs adresses IP sources), cela a pris 3,8842415850296845s. Mon temps initial a pris 16,544873371035163s. . L'efficacité s'est beaucoup améliorée. Bien que l'ordre de grandeur soit encore de quelques secondes, il ne s'agit que d'un fichier par jour. En même temps, cela m'a aidé à découvrir que le problème d'efficacité le plus grave est en fait l'extraction des lignes de journaux qui répondent aux exigences de la fonction. Merci à tous pour vos réponses et votre participation, merci !