2012-09-26 108 views
1

在一個比較函數我bascially尋找一個模式(例如「AAA」)長二進制對象(例如,aaaAAAbbbBBB)Python - 通過二進制對象「窗口化」迭代?

我通過文件工作向後內(我知道這場比賽會更靠近端比開始),加法1個字節到可變正被檢查的匹配:發現

1. aaaAAAbbbBB[B] 
2. aaaAAAbbbB[BB] 
3. aaaAAAbbb[BBB] 
4. aaaAAAbb[bBBB] 
5. ... 
n. aaa[AAAbbbBBB] 

匹配,偏移= -n

鑑於我知道我的圖案是3種元素很久以來,我想知道我是否可以簡單地對搜索變量進行窗口而不是增加搜索變量 - 當它變得非常緩慢時比賽是深列表中的百萬元 - 同一數據的窗口看法是:

1. aaaAAAbbb[BBB] 
2. aaaAAAbb[bBB]B 
3. aaaAAAb[bbB]BB 
4. aaaAAA[bbb]BBB 
5. ... 
n. aaa[AAA]bbbBBB 

發現匹配,偏移量= -n

我目前的搜索是這樣的:

if marker in f_data[-counter:]: 
    offset = (len(f_data)-counter)+len(marker) 
    return offset 

在MATLAB中,我將使用數組尋址來移動數組(例如,我認爲這是不可能的在Python(2.7)

我可以看到一些建議,使用滑動窗口,(()窗口= a [5:8],窗口= a [4:7]等) Rolling or sliding window iterator in Python - 這看起來像一個近似匹配),但我看不到如何實現它或他們引用我不知道如何使用的庫。

是否有內置功能?

+0

你能把整個文件放在內存中嗎? – monkut

回答

5

爲什麼不直接使用rfind()rindex()

haystack = "aaaAAAbbbBBB" 
needle = "AAA" 

pos = haystack.rfind(needle) 

if pos >= 0: 
    print "found at", pos - len(haystack) 
else: 
    print "not found" 
+0

哦,這很有用,謝謝。乾草堆裏可能有n根針,但我只需要最後一根 - 你將如何處理多場比賽? –

+2

@JayGattuso'rfind'從右側搜索。如果你需要最左邊的匹配,使用'find'。 – Marcin

+0

太棒了!我會給它一個,謝謝你的時間 –

0

兩件事情:

(1)標準string類型持有字節,你可以使用正則表達式與此有關。我可以建議你將對象放到一個字符串中,然後執行一個正則表達式搜索。

(2)如果你想這樣做硬盤的方式,有http://docs.python.org/library/itertools.html#itertools.groupby

+0

謝謝,我確實在想RegEx,但我有多個匹配案例,而我當時只需要最後一個(在我知道匹配會有多深之前),我的方法似乎是合理的。我懷疑我正在做錯事情! –

+0

@JayGattuso我不明白爲什麼只需要最後一個排除正則表達式匹配,或者確實是'rfind'。 – Marcin

+0

排除更多我不知道如何處理多個匹配的情況,而不是與工具本身的問題... :) –

0

我認爲這使用了你提到的window()迭代器函數。

>>> l = "ABCABACAAASSD" 
>>> from itertools import islice 
>>> 
>>> def window(seq, n=2): 
...  "Returns a sliding window (of width n) over data from the iterable" 
...  " s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...     " 
...  it = iter(seq) 
...  result = tuple(islice(it, n)) 
...  if len(result) == n: 
...   yield result 
...  for elem in it: 
...   result = result[1:] + (elem,) 
...   yield result 
... 
>>> 
>>> data = [c for c in l] # get each byte/charactor as separate item in list 
>>> data 
['A', 'B', 'C', 'A', 'B', 'A', 'C', 'A', 'A', 'A', 'S', 'S', 'D'] 
>>> for idx, elements in enumerate(window(reversed(data), n=3)): 
...  section = "".join(elements) 
...  if section == "AAA": 
...   print "found at {}!".format(idx) 
... 
found at 3! 
>>> 

爲了解釋:

  • reversed()需要在列表中,並與以相反的順序的元素
  • window()發生在一個迭代的對象(列表,元組,迭代器)返回迭代並返回n元素的數量,一次移動索引1元素。
  • enumerate()需要一個迭代並簡單地附加一個計數器,所以它會返回計數器/位置和給定的元素項。
+0

謝謝,有一天我希望能夠遇到類似這樣的代碼並理解它!......我懷疑根源在於我以錯誤的方式處理這個過程。 –