簡體   English   中英

在格式中找到包含時間元組的列表中的最大時間值('小時','分鍾','上午/下午')

[英]Find maximum value of time in list containing tuples of time in format ('hour', 'min', 'AM/PM')

我有一個代表不同時間的元組列表

timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'), 
('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'), 
('4', '10', 'PM')]

我希望從列表中返回最大值,經過一些搜索后,我意識到我可以使用最大鍵來首先搜索AM或PM。
print(max(timeList, key = operator.itemgetter(2)))

然而,當我運行這個時,我得到了錯誤的最大值('4', '12', 'PM')我想到了它,並且它不僅沒有意義,因為8:23應該是最大值,但是我也意識到12:48可能會返回最大值,因為它是PM,在搜索中技術上也大於8。

話雖如此,如果無法更改列表的格式,我怎么能得到最大值才能找到最新的可能時間。

只需定義一個合適的鍵功能。 你想int(hour)int(minute)'PM'已經字典順序高於"AM" ,但應首先考慮,所以。 此外,您需要采用小時模數12,以便在pm / am 12小於其他數字:

In [39]: timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'),
    ...: ('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'),
    ...: ('4', '10', 'PM')]

In [40]: def key(t):
...:     h, m, z = t
...:     return z, int(h)%12, int(m)
...:

In [41]: max(timeList,key=key)
Out[41]: ('8', '23', 'PM')

但是最有意義的是實際使用datetime.time對象,而不是假裝一個字符串元組是一種存儲時間的好方法。

所以類似於:

In [49]: def to_time(t):
    ...:     h, m, z = t
    ...:     h, m = int(h)%12, int(m)
    ...:     if z  == "PM":
    ...:         h += 12
    ...:     return datetime.time(h, m)
    ...:

In [50]: real_time_list = list(map(to_time, timeList))

In [51]: real_time_list
Out[51]:
[datetime.time(16, 12),
 datetime.time(20, 23),
 datetime.time(4, 3),
 datetime.time(1, 34),
 datetime.time(12, 48),
 datetime.time(4, 13),
 datetime.time(11, 9),
 datetime.time(15, 12),
 datetime.time(16, 10)]

In [52]: list(map(str, real_time_list))
Out[52]:
['16:12:00',
 '20:23:00',
 '04:03:00',
 '01:34:00',
 '12:48:00',
 '04:13:00',
 '11:09:00',
 '15:12:00',
 '16:10:00']

注意,現在max “只是工作”:

In [54]: t = max(real_time_list)

In [55]: print(t)
20:23:00

如果你需要一個漂亮的字符串來打印,那么只需要進行格式化:

In [56]: print(t.strftime("%I:%M %p"))
08:23 PM

為什么不在數據中添加結構?

from datetime import datetime

max(datetime.strptime(''.join(x), '%I%M%p') for x in timeList)

# datetime.datetime(1900, 1, 1, 20, 23)
# i.e. 8.23pm

雖然您說“不應更改列表的格式”,但這正是所有解決方案為執行比較而隱式執行的操作。

具有max函數的key param用於通知max要執行最大操作的值。 itemgetter(2)獲取第二個索引處的值,按字典順序,“PM”是索引2列表中的最高值(按字典順序'PM'>'AM')。 您可以使用lambda函數計算索引0和1處元組的最大值,如下所示:

>>> timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'), ('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'), ('4', '10', 'PM')]

# type-casting it to `int` to avoid incorrect result 
# due lexicographical comparision of `str`
>>> max(timeList, key=lambda x: (x[2], int(x[0]), int(x[1])))
('12', '48', 'PM')            #   ^      ^         ^ Third priority to `int` value of minute
                              #   ^      ^ Second priority to int value of `hour`
                              #   ^ First priority to lexicographically sort on `AM`/`PM`

或者,您在datetime.datetime對象上執行比較:

>>> from datetime import datetime

>>> max(timeList, key=lambda x: datetime.strptime('{}:{}{}'.format(*x), '%I:%M%p'))
('8', '23', 'PM')

我認為你應該最初創建datetime.datetime列表而不是時間tuples

添加到解決方案,您還可以使用datetime排序:

from datetime import datetime

timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'), 
('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'), 
('4', '10', 'PM')]

sorted(timeList, key=lambda x: datetime.strptime(''.join(x), '%I%M%p'))[-1]

返回:

('8', '23', 'PM')

這實際上是在pandas中優雅地實現的,它允許一個MultiIndex,然后我們可以對它進行排序並占據頭部:

import numpy as np
import pandas as pd

timeList = [('4','12','PM'),  ('8','23','PM'),  ('4','03','AM'),
            ('1','34','AM'),  ('12','48','PM'), ('4','13','AM'),
            ('11','09','AM'), ('3','12','PM'),  ('4','10','PM')]

timeDf = pd.DataFrame(timeList, columns=['hr','min','meridiem'])
timeDf.set_index(['meridiem','hr','min'], inplace=True, drop=True)

#timeDf['value'] = np.random.randint(1,10, timeDf.shape[0]) # np.nan

timeDf.sort_index(level=0, ascending=False, inplace=True) # sort by meridiem, then the remaining cols (alphanumeric string comparison)
timeDf.index[0]
# ('PM', '8', '23')

筆記:

  • 如果你想將hr,min,meridiem保留為df中的列,那么使用set_index(..., drop=False)
  • 正如AntonvBR指出的那樣,如果時間戳也包含一個時區,那么我們就不能再對多個不同的(字符串)字段使用簡單排序了; 我們想要計算基礎日期時間,然后將其用作排序鍵。

看起來像你的timeList是時候。 也許它解析它是有道理的嗎?

 max([datetime.strptime("{}:{} {}".format(t[0],t[1],t[2]),'%I:%M %p') for t in timeList]).strftime("%H:%M")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM