@aggregion/binary-filter
Advanced tools
Comparing version 0.1.3 to 0.2.0
export declare class BinaryFilter { | ||
private readonly maxLength; | ||
private readonly buffer; | ||
readonly buffer: Uint8Array; | ||
maxLength: number; | ||
length: number; | ||
constructor(maxLength: number); | ||
static from(array: number[]): BinaryFilter; | ||
constructor(maxLengthOrBuffer: number | Uint8Array, maxLength?: number); | ||
add(value: number): void; | ||
@@ -10,3 +11,6 @@ has(value: number): boolean; | ||
private setBit; | ||
private reCalcLength; | ||
union(filter: BinaryFilter): BinaryFilter; | ||
intersect(filter: BinaryFilter): BinaryFilter; | ||
} | ||
export default BinaryFilter; |
@@ -5,7 +5,20 @@ "use strict"; | ||
class BinaryFilter { | ||
constructor(maxLength) { | ||
this.maxLength = maxLength; | ||
static from(array) { | ||
const max = array.reduce((a, b) => Math.max(a, b), -Infinity); | ||
const filter = new BinaryFilter(max); | ||
array.forEach((v) => filter.add(v)); | ||
return filter; | ||
} | ||
constructor(maxLengthOrBuffer, maxLength = 0) { | ||
this.maxLength = 0; | ||
this.length = 0; | ||
const size = Math.ceil(maxLength / 8) + 1; | ||
this.buffer = new Uint8Array(size); | ||
if (maxLengthOrBuffer instanceof Uint8Array) { | ||
this.buffer = maxLengthOrBuffer; | ||
this.maxLength = maxLength; | ||
this.reCalcLength(); | ||
} | ||
else { | ||
this.buffer = new Uint8Array(Math.ceil(maxLengthOrBuffer / 8) + 1); | ||
this.maxLength = maxLengthOrBuffer; | ||
} | ||
} | ||
@@ -42,2 +55,42 @@ add(value) { | ||
} | ||
reCalcLength() { | ||
this.length = 0; | ||
this.buffer.forEach((octet, byteNum) => { | ||
for (let bitInByte = 0; bitInByte <= 7; bitInByte++) { | ||
if ((this.buffer[byteNum] >> bitInByte) % 2 === 1) { | ||
this.length++; | ||
} | ||
} | ||
}); | ||
} | ||
union(filter) { | ||
const maxLength = Math.max(filter.maxLength, this.maxLength); | ||
const buffer = new Uint8Array(Math.ceil(maxLength / 8) + 1); | ||
return new BinaryFilter(buffer.map((octet, index) => { | ||
if (this.buffer[index] && filter.buffer[index]) { | ||
return this.buffer[index] | filter.buffer[index]; | ||
} | ||
else if (this.buffer[index]) { | ||
return this.buffer[index]; | ||
} | ||
else { | ||
return filter.buffer[index]; | ||
} | ||
}), maxLength); | ||
} | ||
intersect(filter) { | ||
const maxLength = Math.max(filter.maxLength, this.maxLength); | ||
const buffer = new Uint8Array(Math.ceil(maxLength / 8) + 1); | ||
return new BinaryFilter(buffer.map((octet, index) => { | ||
if (this.buffer[index] && filter.buffer[index]) { | ||
return this.buffer[index] & filter.buffer[index]; | ||
} | ||
else if (this.buffer[index]) { | ||
return 0; | ||
} | ||
else { | ||
return 0; | ||
} | ||
}), maxLength); | ||
} | ||
} | ||
@@ -44,0 +97,0 @@ exports.BinaryFilter = BinaryFilter; |
{ | ||
"name": "@aggregion/binary-filter", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/binaryFilter.js", |
@@ -10,2 +10,4 @@ # JS Binary Filter | ||
Binary filter add entries: | ||
``` | ||
@@ -25,2 +27,19 @@ import {BinaryFilter} from '@aggregion/binary-filter' | ||
filter.length // 3 | ||
``` | ||
Create from list | ||
``` | ||
const filter = Binary.from([1,2,3]); | ||
``` | ||
Union and intersections | ||
``` | ||
const filter1 = Binary.from([1,2,3]); | ||
const filter2 = Binary.from([2,3,5]); | ||
const union = filter1.union(filter2); // contains 1,2,3,5 | ||
const intersection = filter2.intersect(filter2); // contains 2,3 | ||
``` |
@@ -32,2 +32,41 @@ import { BinaryFilter } from './binaryFilter'; | ||
}); | ||
test('should create filter from list', () => { | ||
const testArr = [1, 2, 3, 1, 123, 232, 432, 432, 1, 2, 1000000]; | ||
const filter = BinaryFilter.from(testArr); | ||
expect(filter.length).toEqual(7); | ||
}); | ||
test('should create union', () => { | ||
const filter1 = BinaryFilter.from([1,2,3,6]); | ||
const filter2 = BinaryFilter.from([3,5,6,12]); | ||
const union = filter1.union(filter2); | ||
expect(union.length).toEqual(6); | ||
expect(union.has(1)).toBeTruthy(); | ||
expect(union.has(2)).toBeTruthy(); | ||
expect(union.has(3)).toBeTruthy(); | ||
expect(union.has(5)).toBeTruthy(); | ||
expect(union.has(6)).toBeTruthy(); | ||
expect(union.has(12)).toBeTruthy(); | ||
expect(union.has(7)).toBeFalsy(); | ||
}); | ||
test('should create intersect filter', () => { | ||
const filter1 = BinaryFilter.from([1,2,3,6]); | ||
const filter2 = BinaryFilter.from([3,5,6,12]); | ||
const intersection = filter1.intersect(filter2); | ||
expect(intersection.length).toEqual(2) | ||
expect(intersection.has(3)).toBeTruthy(); | ||
expect(intersection.has(6)).toBeTruthy(); | ||
expect(intersection.has(1)).toBeFalsy(); | ||
expect(intersection.has(12)).toBeFalsy(); | ||
}) | ||
}); |
export class BinaryFilter { | ||
private readonly buffer: Uint8Array; | ||
readonly buffer: Uint8Array; | ||
maxLength = 0; | ||
length = 0; | ||
constructor(private readonly maxLength: number) { | ||
const size = Math.ceil(maxLength / 8) + 1; | ||
this.buffer = new Uint8Array(size); | ||
static from(array: number[]) { | ||
const max = array.reduce((a, b) => Math.max(a, b), -Infinity); | ||
const filter = new BinaryFilter(max); | ||
array.forEach((v) => filter.add(v)); | ||
return filter; | ||
} | ||
constructor(maxLengthOrBuffer: number | Uint8Array, maxLength = 0) { | ||
if (maxLengthOrBuffer instanceof Uint8Array) { | ||
this.buffer = maxLengthOrBuffer; | ||
this.maxLength = maxLength; | ||
this.reCalcLength(); | ||
} else { | ||
this.buffer = new Uint8Array(Math.ceil(maxLengthOrBuffer / 8) + 1); | ||
this.maxLength = maxLengthOrBuffer; | ||
} | ||
} | ||
add(value: number) { | ||
@@ -40,4 +54,51 @@ if (value > this.maxLength) { | ||
} | ||
private reCalcLength() { | ||
this.length = 0; | ||
this.buffer.forEach((octet, byteNum) => { | ||
for (let bitInByte = 0; bitInByte <= 7; bitInByte++) { | ||
if ((this.buffer[byteNum] >> bitInByte) % 2 === 1) { | ||
this.length++; | ||
} | ||
} | ||
}); | ||
} | ||
union(filter: BinaryFilter) { | ||
const maxLength = Math.max(filter.maxLength, this.maxLength); | ||
const buffer = new Uint8Array(Math.ceil(maxLength / 8) + 1); | ||
return new BinaryFilter( | ||
buffer.map((octet, index) => { | ||
if (this.buffer[index] && filter.buffer[index]) { | ||
return this.buffer[index] | filter.buffer[index]; | ||
} else if (this.buffer[index]) { | ||
return this.buffer[index]; | ||
} else { | ||
return filter.buffer[index]; | ||
} | ||
}), | ||
maxLength, | ||
); | ||
} | ||
intersect(filter: BinaryFilter) { | ||
const maxLength = Math.max(filter.maxLength, this.maxLength); | ||
const buffer = new Uint8Array(Math.ceil(maxLength / 8) + 1); | ||
return new BinaryFilter( | ||
buffer.map((octet, index) => { | ||
if (this.buffer[index] && filter.buffer[index]) { | ||
return this.buffer[index] & filter.buffer[index]; | ||
} else if (this.buffer[index]) { | ||
return 0; | ||
} else { | ||
return 0; | ||
} | ||
}), | ||
maxLength, | ||
); | ||
} | ||
} | ||
export default BinaryFilter; |
Sorry, the diff of this file is not supported yet
15842
299
43