|
| 1 | +// Define a Bloom filter class |
| 2 | +class BloomFilter { |
| 3 | + // Constructor takes the size of the bit array and the number of hash functions |
| 4 | + constructor(size, numHashes) { |
| 5 | + this.size = size; // The size of the bit array |
| 6 | + this.numHashes = numHashes; // The number of hash functions |
| 7 | + this.bitArray = new Array(size).fill(0); // Initialize the bit array with zeros |
| 8 | + } |
| 9 | + |
| 10 | + // A simple hash function that takes a string and returns an integer |
| 11 | + hash(str) { |
| 12 | + let hash = 0; |
| 13 | + for (let i = 0; i < str.length; i++) { |
| 14 | + hash = (hash * 31 + str.charCodeAt(i)) % this.size; |
| 15 | + } |
| 16 | + return hash; |
| 17 | + } |
| 18 | + |
| 19 | + // A method to generate multiple hashes for a given element |
| 20 | + // It uses double hashing technique to avoid correlation between hashes |
| 21 | + generateHashes(element) { |
| 22 | + let hashes = []; |
| 23 | + let hash1 = this.hash(element); // First hash |
| 24 | + let hash2 = this.hash(hash1 + element); // Second hash |
| 25 | + for (let i = 0; i < this.numHashes; i++) { |
| 26 | + // Generate more hashes by adding multiples of second hash to first hash |
| 27 | + let newHash = (hash1 + i * hash2) % this.size; |
| 28 | + hashes.push(newHash); |
| 29 | + } |
| 30 | + return hashes; |
| 31 | + } |
| 32 | + |
| 33 | + // A method to add an element to the Bloom filter |
| 34 | + add(element) { |
| 35 | + // Generate the hashes for the element |
| 36 | + let hashes = this.generateHashes(element); |
| 37 | + // Set the bits at the hashed positions to 1 |
| 38 | + for (let hash of hashes) { |
| 39 | + this.bitArray[hash] = 1; |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + // A method to check if an element is in the Bloom filter |
| 44 | + contains(element) { |
| 45 | + // Generate the hashes for the element |
| 46 | + let hashes = this.generateHashes(element); |
| 47 | + // Check if all the bits at the hashed positions are 1 |
| 48 | + for (let hash of hashes) { |
| 49 | + if (this.bitArray[hash] === 0) { |
| 50 | + return false; // Definitely not in the set |
| 51 | + } |
| 52 | + } |
| 53 | + return true; // Probably in the set, but could be a false positive |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +// Example usage |
| 58 | +// Create a Bloom filter with size 100 and 3 hash functions |
| 59 | +let bf = new BloomFilter(100, 3); |
| 60 | + |
| 61 | +// Add some elements to the filter |
| 62 | +bf.add("apple"); |
| 63 | +bf.add("banana"); |
| 64 | +bf.add("cherry"); |
| 65 | + |
| 66 | +// Check if some elements are in the filter |
| 67 | +console.log(bf.contains("apple")); // true |
| 68 | +console.log(bf.contains("banana")); // true |
| 69 | +console.log(bf.contains("cherry")); // true |
| 70 | +console.log(bf.contains("durian")); // false |
| 71 | +console.log(bf.contains("elderberry")); // false |
| 72 | + |
| 73 | +// Add more elements to the filter |
| 74 | +bf.add("fig"); |
| 75 | +bf.add("grape"); |
| 76 | +bf.add("honeydew"); |
| 77 | + |
| 78 | +// Check if some elements are in the filter |
| 79 | +console.log(bf.contains("fig")); // true |
| 80 | +console.log(bf.contains("grape")); // true |
| 81 | +console.log(bf.contains("honeydew")); // true |
| 82 | +console.log(bf.contains("iceberg")); // false |
| 83 | +console.log(bf.contains("jackfruit")); // false |
| 84 | + |
| 85 | +// There is a chance of false positives, but not false negatives |
| 86 | +console.log(bf.contains("kiwi")); // false (correct) |
| 87 | +console.log(bf.contains("lime")); // true (false positive) |
| 88 | +// const b = new BloomFilters(); |
| 89 | +module.exports = BloomFilters; |
0 commit comments