[英]Matching overlapping Intervals (Dictionary) in Python
所以,我試圖通過 python 解決一些隨機問題並被困在邏輯上。 問題是:我有多個視頻以及它們的運行時間或運行長度。 現在,我想維護 2 個列表。 如果“已同步”,則為 1 個列表,而另一個為“未同步”。 如果流的運行時間差異小於或等於 2 秒,我們決定“同步”。 否則,它們不會同步。 如果我們有多個匹配的流,那么我們采用具有最高匹配計數/數量的流。
我能夠想出一種非常簡單/緩慢的方法來分割和配對這些文件。 但是,當我獲得不同的數據集時,我的邏輯失敗了。
這是我寫的:
from datetime import datetime
# same_streams_old = {
"Stream_1": "0:24:08.925167",
"Stream_2": "0:24:08.990644",
"Stream_3": "0:24:08.990644",
"Stream_4": "0:24:12.118778",
"Stream_5": "0:24:12.118778",
"stream_6": "0:24:10.075066"
}
same_streams = {
"Stream_1": "0:24:08.925167",
"Stream_2": "0:24:12.118778",
"Stream_3": "0:23:11.057711",
"Stream_4": "0:24:12.118778",
"Stream_5": "0:24:10.075066",
"Stream_6": "0:24:08.990644"
}
keys = []
values = []
final_synced_video_files = []
final_non_synced_video_files = []
def get_time_diff(episode_run_time, episode_time):
prev_episode_time = datetime.strptime(episode_run_time, '%H:%M:%S.%f')
current_episode_time = datetime.strptime(episode_time, '%H:%M:%S.%f')
time_diff = prev_episode_time - current_episode_time
if current_episode_time > prev_episode_time:
time_diff = current_episode_time - prev_episode_time
return float(time_diff.seconds)
for key, value in same_streams.items():
keys.append(key)
values.append(value)
for key in keys:
for _key in keys:
if key != _key:
diff = get_time_diff(same_streams[key], same_streams[_key])
if diff <= 1.5:
final_synced_video_files.append(key)
else:
pass
final_synced_video_files = list(set(final_synced_video_files))
final_non_synced_video_files = list(set(keys) - set(final_synced_video_files))
print("Synced Files : {0}".format(final_synced_video_files))
print("Non Synced Files : {0}".format(final_non_synced_video_files))
如您所見,匹配最多的流是stream_1
、 stream_2
、 stream_3
和stream_6
。
我寫的還沒有比較最大計數。 然而,當我在做這件事時,我覺得這並不是真正有效的解決這個問題的好方法。 任何人的任何輸入?
我嘗試了一些重疊間隔的方法,然后得到了這個: REPL LINK
但是,如果您運行看到兩個same_streams
字典,您會看到結果不是我想要實現的。 對此的任何幫助都會很棒。
編輯:我需要獲得彼此相差 2 秒的流。 例如:在same_streams_old
,期望的結果是流 1,2,3 & 6。然而,在字典same_streams
,期望的結果是流 2,4 & 5。
基本上,我需要查看哪些流可以“混合”在一起,哪些不能混合。
好的,所以下面的打印例程可能有點亂,但請耐心等待,它們僅用於調試,完成后您可能不需要它們。 我知道這是一個很長的答案,但請仔細閱讀..
簡短回答:
您的問題可能來自這樣一個事實,即當您從 string 轉換為datetime
時會丟失小數精度,它將秒視為整數。 然而, timedelta
對象有一個名為total_seconds()
的方法,它提供亞秒級分辨率。 有關詳細信息,請參閱此文檔或通用文檔。 只需將get_time_diff()
的return
語句更改為,
return float(time_diff.total_seconds())
長答案的動機:
我不確定您要使用(非和)同步列表實現什么目標:您可能會遇到流a與流b同步,而流c與d同步的情況,但是c和d不與a和b同步。 他們都應該在你的synced_list
嗎? 根據您想對列表做什么,我會考慮使用下面描述的同步矩陣,而不是您的列表,因為它們會丟失很多信息。
長答案:
讓我介紹一下同步矩陣的概念。 它將完整描述您的哪些流相互同步:
同步矩陣:對稱矩陣; 當且僅當流“i”和“j”同步時,矩陣中的單元格 (i,j) 為 TRUE。 否則,單元格值為 FALSE。 因此,對角線 (.) 完全為 TRUE,因為流始終與自身同步。
1 2 3 4 ________ 1 | . TTF 2 | . TF 3 | . F 4 | .
“T”為真,“F”為假:顯然從上面的示例圖中,流 1 與流 2 同步,但與流 4 不同步。
對於您的示例,創建這樣的同步矩陣非常簡單:
def is_synced(key_1, key_2):
max_allowed_desync = 1.5
return max_allowed_desync > get_time_diff(same_streams[key_1], same_streams[key_2])
keys = same_streams.keys()
keys.sort() # VERY IMPORTANT, for the synced matrix to be constructed correctly; also make 's' uppercase for "stream_6" in OP.
# The complete matrix ..
full_sync_matrix = [[is_synced(k1,k2) for k2 in keys] for k1 in keys]
# We can optimize (memory usage) to only get the half matrix, since it's symmetric anyway; also excluding the diagonal.
half_sync_matrix = [[is_synced(k1,k2) for k2 in keys[curr+1:]] for curr,k1 in enumerate(keys)]
現在,讓我們實現兩個函數來打印/顯示同步矩陣:
# Print a HALFED sync matrix
def print_sync_half_matrix(sm):
string = ""
for i,row in enumerate(sm):
string += "\n" + " "*i*2
for col in row:
string += " " + ("T" if col else "F")
print(string)
# Print a COMPLETE sync_matrix
def print_sync_full_matrix(sm):
string = ""
for row in sm:
string += "\n"
for col in row:
string += " " + ("T" if col else "F")
print(string)
然后,對於您提供的數據集,我得到:
same_streams = {
"Stream_1": "0:24:08.925167",
"Stream_2": "0:24:08.990644",
"Stream_3": "0:24:08.990644",
"Stream_4": "0:24:12.118778",
"Stream_5": "0:24:12.118778",
"Stream_6": "0:24:10.075066"
} # note that "Stream_6" previously had a lower case 's'!
print_sync_half_matrix(half_sync_matrix)
# 1 2 3 4 5 6
# 1 T T F F T
# 2 T F F T
# 3 F F T
# 4 T F
# 5 F
請記住,矩陣/打印中不包含對角線! 此處的結果是正確的,並且符合輸入的預期。 讓我們打印出一些時差以獲得更多情報,
for stream_key in same_stream:
print("Stream_1 ~ "+stream_key+": "+str(get_time_diff(same_streams["Stream_1"], same_streams[stream_key])))
.. 很快就會發現你的時間戳已經失去了它的十進制精度:
Stream_1 ~ Stream_5: 3.0
Stream_1 ~ Stream_4: 3.0
# ...
如果我們查看datetime
的文檔,我們會發現它將時間視為整數秒。 因此,當您從get_time_diff
函數中的datetime
對象請求seconds
時,微秒精度會丟失。 只需通過從 deltatime 方法.total_seconds()
請求秒來解決..
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.