簡體   English   中英

在 Python 中匹配重疊區間(字典)

[英]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_1stream_2stream_3stream_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同步,而流cd同步的情況,但是cdab同步。 他們都應該在你的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.

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