python實現布隆過濾器對資料去重

2021-07-07 04:35:56 字數 4019 閱讀 2813

一、直觀的資料去重方式

通常我們採用如下演算法對一組長度為n的資料d進行去重時。

s1.在資料中取出第x個資料(1≤xs2.在資料中取出第y個資料(xs3.比較d[x]和d[y],若相同丟棄d[y],重複s2,s3直到y=n

s4.重複s1,s2,s3直到x=n-1

此演算法時間複雜度近似t(n)=o(1/2n²),空間需求為size(d)。

假設現有一組資料d,單條長度500位元組,共有108條,有一台計算機,每秒處理106次資料對比。由此可以計算,該次去重共需要的儲存空間為s=108*500=5*1010=50g,所需要的時間t=1/2*(108)²*1/106=5*109秒≈158年

由此可見,對於大量的資料去重任務來說,這個演算法是不可行的。

當然這個演算法也可以通過提公升硬體來減少儲存和處理時間,如:將資料儲存在磁碟,在需要的時候載入到記憶體,使用磁碟陣列來增加讀取速度,來解決儲存問題。增加cpu核數來增加比對速度來減少時間等。但這些都增加了成本

二、布隆過濾器

布隆過濾器是由burton howard bloom於2023年提出,他是一種space efficient的概率模型資料結構,用於判斷乙個元素是否在集合中。

乙個空的布隆過濾器是乙個m bit的bitmap,每一位都初始化為0。布隆過濾器定義有k個hash函式,對輸入的資料生成k個hash值,定義有乙個map函式將k個hash值對映到bitmap的k個位。如下圖:

存入時將資料對應的bitmap中的k個位都置為1,檢索時只需要比對資料對應的k個位是否都為1。布隆過濾器不允許從中刪除資料,因為刪除資料時可能會影響其他資料對應的位,造成刪除其他資料。

三、布隆過濾器的實現(python)

bloom.py

importrandom

frombitmapimportbitmap

class

bloomfilter:

def__init__

(self

, mapsize=

160000

, max_node_size=

10000

, random_num=8):

self

.m = mapsize

self

.n = max_node_size

self

.k = random_num

self

.bitmap = bitmap(

maxnum

=self

.m)       

self

.count = 0;

pass

def

set(

self

, string):

calcmap =

self

.calcmap(string)

forxincalcmap:

self

.bitmap.set(x)

pass

def

test(

self

, string):

calcmap =

self

.calcmap(string)

forxincalcmap:

if notself

.bitmap.test(x):

return false

return true

def

calcmap(

self

, string):

r = random.random(string)

lv1random = [r.random()forxinrange

(self

.k)]

return[

int(random.random(x).random()*

self

.m)forxinlv1random]

__init__ 中mapsize為bitmap的size,max_node_size為最大容納的資料個數,random_num生成隨機數個數,這裡使用偽隨機數來代替hash函式。

set將輸入的資料存入到布隆過濾器

test測試輸入的資料是否在布隆過濾器章

calcmap計算輸入的資料對映到bitmap的位置

bitmap.py

importarray

class

bitmap(

object

):"""

bitmap class

"""bitmask= [

0x01

, 0x02

, 0x04

, 0x08

, 0x10

, 0x20

, 0x40

, 0x80

]bit_cnt = [

bin(i).count(

"1")foriinrange

(256

)]def__init__

(self

, maxnum=0):

"""create a bitmap

"""nbytes =

int((maxnum +

7) / 8)

self

.bitmap = array.array(

'b',

[0foriinrange

(nbytes)])

def

set(

self

, pos):

"""set the value of bit@pos to 1

"""self

.bitmap[

int(pos /

8)] |=

self

.bitmask[pos % 8]

def

test(

self

, pos):

"""return bit value

"""return(

self

.bitmap[

int(pos /

8)] &

self

.bitmask[pos %

8]) != 0

set為在bitmap特定索引處置1,

test為測試在bitmap特定索引處是否為1

四、利用布隆過濾器

我們可以採用以下演算法利用布隆過濾器來對一組長度為n的資料d去重

s1取第x個資料(1≤x≤n)

s2在布隆過濾器中檢索d[x]是否存在於布隆過濾器,若存在則丟棄

s3將d[x]存入到布隆過濾器

s4重複s1-3直到x=n

這個演算法的時間複雜度t(n)=o(n),空間需求s=m/8,m為bitmap的總位數,m>n且m/n>k,n為資料d包含的資料條數,k為hash函式的個數。

在k=8,m/n=32時,對上文提到的資料進行去重處理,所需要的時間t=108/106=100秒,空間需求s=32*108/8=400m。相對於上文的演算法,改演算法可以大大節省時間和儲存空間。

python過濾器 布隆過濾器 python實現

布隆過濾器是什麼?在爬蟲爬取網頁的時候,我們會做的一件事情是判斷這個網頁是否之前已經爬取過。這個檢驗步驟在之前的文章裡我是用了乙個 集合 來儲存已經爬取過的網頁,而在計算機當中,使用hash表來儲存。hash表的好處就是能夠快速定位,而它的缺點也眾所皆知,就是儲存空間的浪費。為什麼會浪費儲存空間呢?...

布隆過濾器

布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...

布隆過濾器

布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...