diff --git a/README.md b/README.md index a290e12..105829b 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ A heap-based implementation of priority queue in javascript with typescript supp * [front](#front) * [back](#back) * [dequeue (pop)](#dequeue-pop) + * [contains](#contains) * [remove](#remove) * [isEmpty](#isEmpty) * [size](#size) @@ -248,6 +249,16 @@ console.log(bidsQueue.pop()); // { id: 5, value: 12000 } console.log(bidsQueue.pop()); // { id: 7, value: 8000 } ``` +### contains +checks if the queue contains an element that meet a criteria in O(n*log(n)) runtime. + +```js +carsQueue.contains((car) => car.price === 50000); // true +carsQueue.contains((car) => car.price === 200000); // false +numbersQueue.contains((n) => n === 4); // true +numbersQueue.contains((n) => n === 10); // false +``` + ### remove removes all elements that meet a criteria in O(n*log(n)) runtime and returns a list of the removed elements. diff --git a/src/maxPriorityQueue.d.ts b/src/maxPriorityQueue.d.ts index d183a91..9052505 100644 --- a/src/maxPriorityQueue.d.ts +++ b/src/maxPriorityQueue.d.ts @@ -12,6 +12,7 @@ export class MaxPriorityQueue { dequeue(): T; pop(): T; remove(cb: (value: T) => boolean): T[]; + contains(cb: (value: T) => boolean): boolean; toArray(): T[]; clear(): void; static fromArray(values: T[], getCompareValue?: IGetCompareValue): MaxPriorityQueue; diff --git a/src/maxPriorityQueue.js b/src/maxPriorityQueue.js index 8c41d60..1e64a8a 100644 --- a/src/maxPriorityQueue.js +++ b/src/maxPriorityQueue.js @@ -105,6 +105,32 @@ class MaxPriorityQueue { return removed; } + /** + * Checks if the queue contains an element that matches a criteria + * @public + * @param {function} cb + * @returns {boolean} + */ + contains(cb) { + if (typeof cb !== 'function') { + throw new Error('MaxPriorityQueue contains expects a callback'); + } + + let found = false; + const dequeued = []; + while (!this.isEmpty()) { + const popped = this.pop(); + dequeued.push(popped); + if (cb(popped)) { + found = true; + break; + } + } + + dequeued.forEach((val) => this.push(val)); + return found; + } + /** * Returns the number of elements in the queue * @public diff --git a/src/minPriorityQueue.d.ts b/src/minPriorityQueue.d.ts index 183c3a4..523fd59 100644 --- a/src/minPriorityQueue.d.ts +++ b/src/minPriorityQueue.d.ts @@ -12,6 +12,7 @@ export class MinPriorityQueue { dequeue(): T; pop(): T; remove(cb: (value: T) => boolean): T[]; + contains(cb: (value: T) => boolean): boolean; toArray(): T[]; clear(): void; static fromArray(values: T[], getCompareValue?: IGetCompareValue): MinPriorityQueue; diff --git a/src/minPriorityQueue.js b/src/minPriorityQueue.js index 113c2f8..1da0e99 100644 --- a/src/minPriorityQueue.js +++ b/src/minPriorityQueue.js @@ -104,6 +104,32 @@ class MinPriorityQueue { return removed; } + /** + * Checks if the queue contains an element that matches a criteria + * @public + * @param {function} cb + * @returns {boolean} + */ + contains(cb) { + if (typeof cb !== 'function') { + throw new Error('MinPriorityQueue contains expects a callback'); + } + + let found = false; + const dequeued = []; + while (!this.isEmpty()) { + const popped = this.pop(); + dequeued.push(popped); + if (cb(popped)) { + found = true; + break; + } + } + + dequeued.forEach((val) => this.push(val)); + return found; + } + /** * Returns the number of elements in the queue * @public diff --git a/src/priorityQueue.d.ts b/src/priorityQueue.d.ts index 9de0aeb..2c0382b 100644 --- a/src/priorityQueue.d.ts +++ b/src/priorityQueue.d.ts @@ -12,6 +12,7 @@ export class PriorityQueue { dequeue(): T; pop(): T; remove(cb: (value: T) => boolean): T[]; + contains(cb: (value: T) => boolean): boolean; toArray(): T[]; clear(): void; static fromArray(values: T[], compare: ICompare): PriorityQueue; diff --git a/src/priorityQueue.js b/src/priorityQueue.js index b8fcc3e..825c282 100644 --- a/src/priorityQueue.js +++ b/src/priorityQueue.js @@ -105,6 +105,32 @@ class PriorityQueue { return removed; } + /** + * Checks if the queue contains an element that matches a criteria + * @public + * @param {function} cb + * @returns {boolean} + */ + contains(cb) { + if (typeof cb !== 'function') { + throw new Error('PriorityQueue contains expects a callback'); + } + + let found = false; + const dequeued = []; + while (!this.isEmpty()) { + const popped = this.pop(); + dequeued.push(popped); + if (cb(popped)) { + found = true; + break; + } + } + + dequeued.forEach((val) => this.push(val)); + return found; + } + /** * Returns the number of elements in the queue * @public diff --git a/test/PriorityQueue.test.js b/test/PriorityQueue.test.js index 2137469..b8df623 100644 --- a/test/PriorityQueue.test.js +++ b/test/PriorityQueue.test.js @@ -108,6 +108,15 @@ describe('PriorityQueue', () => { }); }); + describe('contains', () => { + it('checks if the queue contains an element', () => { + const maxQ = new PriorityQueue(charComparator); + charValues.forEach((value) => maxQ.push(value)); + expect(maxQ.contains((c) => c.id === 'z')).to.equal(true); + expect(maxQ.contains((c) => c.id === 'y')).to.equal(false); + }); + }); + describe('remove', () => { it('remove elements that match a criteria', () => { const testArr = [20, 30, 40, 50, 80, 90]; diff --git a/test/maxPriorityQueue.test.js b/test/maxPriorityQueue.test.js index 16a7cfc..0ce101d 100644 --- a/test/maxPriorityQueue.test.js +++ b/test/maxPriorityQueue.test.js @@ -107,6 +107,15 @@ describe('MaxPriorityQueue', () => { }); }); + describe('contains', () => { + it('checks if the queue contains an element', () => { + const testArr = [90, 80, 50, 40, 30, 20]; + const qTest = MaxPriorityQueue.fromArray(testArr.slice()); + expect(qTest.contains((n) => n === 50)).to.equal(true); + expect(qTest.contains((n) => n === 100)).to.equal(false); + }); + }); + describe('remove', () => { it('remove elements that match a criteria', () => { const testArr = [20, 30, 40, 50, 80, 90]; diff --git a/test/minPriorityQueue.test.js b/test/minPriorityQueue.test.js index d6e09be..78b6b00 100644 --- a/test/minPriorityQueue.test.js +++ b/test/minPriorityQueue.test.js @@ -103,6 +103,15 @@ describe('MinPriorityQueue', () => { }); }); + describe('contains', () => { + it('checks if the queue contains an element', () => { + const testArr = [90, 80, 50, 40, 30, 20]; + const qTest = MinPriorityQueue.fromArray(testArr.slice()); + expect(qTest.contains((n) => n === 50)).to.equal(true); + expect(qTest.contains((n) => n === 100)).to.equal(false); + }); + }); + describe('remove', () => { it('remove elements that match a criteria', () => { const testArr = [20, 30, 40, 50, 80, 90];