Skip to content

Commit 90e78ea

Browse files
authored
Merge pull request #55 from datastructures-js/add_remove
add remove method
2 parents 250f302 + db48ab0 commit 90e78ea

12 files changed

+140
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
## [6.3.0] - 2023-05-30
9+
### Added
10+
- `.remove(cb)` to remove all elements that meet a criteria.
11+
812
## [6.2.0] - 2023-01-16
913
### Added
1014
- Symbol.iterator

README.md

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ A heap-based implementation of priority queue in javascript with typescript supp
1818
* [front](#front)
1919
* [back](#back)
2020
* [dequeue (pop)](#dequeue-pop)
21+
* [remove](#remove)
2122
* [isEmpty](#isEmpty)
2223
* [size](#size)
2324
* [toArray](#toarray)
@@ -242,6 +243,17 @@ console.log(bidsQueue.pop()); // { id: 5, value: 12000 }
242243
console.log(bidsQueue.pop()); // { id: 7, value: 8000 }
243244
```
244245

246+
### remove
247+
removes all elements that meet a criteria in O(n*log(n)) runtime and return a list of the removed elements.
248+
249+
```js
250+
carsQueue.remove((car) => car.price === 35000); // [{ year: 2013, price: 35000 }]
251+
252+
numbersQueue.remove((n) => n === 4); // [4]
253+
254+
bidsQueue.remove((bid) => bid.id === 3); // [{ id: 3, value: 1000 }]
255+
```
256+
245257
### isEmpty
246258
checks if the queue is empty.
247259

@@ -255,9 +267,9 @@ console.log(bidsQueue.isEmpty()); // false
255267
returns the number of elements in the queue.
256268

257269
```js
258-
console.log(carsQueue.size()); // 4
259-
console.log(numbersQueue.size()); // 4
260-
console.log(bidsQueue.size()); // 4
270+
console.log(carsQueue.size()); // 3
271+
console.log(numbersQueue.size()); // 3
272+
console.log(bidsQueue.size()); // 3
261273
```
262274

263275
### toArray
@@ -269,19 +281,17 @@ console.log(carsQueue.toArray());
269281
[
270282
{ year: 2013, price: 25000 },
271283
{ year: 2013, price: 30000 },
272-
{ year: 2013, price: 35000 },
273284
{ year: 2010, price: 2000 }
274285
]
275286
*/
276287

277-
console.log(numbersQueue.toArray()); // [ 0, 3, 4, 5 ]
288+
console.log(numbersQueue.toArray()); // [ 0, 3, 5 ]
278289

279290
console.log(bidsQueue.toArray());
280291
/*
281292
[
282293
{ id: 6, value: 4000 },
283294
{ id: 4, value: 1500 },
284-
{ id: 3, value: 1000 },
285295
{ id: 1, value: 1000 }
286296
]
287297
*/
@@ -295,13 +305,12 @@ console.log([...carsQueue]);
295305
[
296306
{ year: 2013, price: 25000 },
297307
{ year: 2013, price: 30000 },
298-
{ year: 2013, price: 35000 },
299308
{ year: 2010, price: 2000 }
300309
]
301310
*/
302311
console.log(carsQueue.size()); // 0
303312

304-
console.log([...numbersQueue]); // [ 0, 3, 4, 5 ]
313+
console.log([...numbersQueue]); // [ 0, 3, 5 ]
305314
console.log(numbersQueue.size()); // 0
306315

307316
for (const bid of bidsQueue) {
@@ -310,7 +319,6 @@ for (const bid of bidsQueue) {
310319
/*
311320
{ id: 6, value: 4000 },
312321
{ id: 4, value: 1500 },
313-
{ id: 3, value: 1000 },
314322
{ id: 1, value: 1000 }
315323
*/
316324
console.log(bidsHeap.size()); // 0

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@datastructures-js/priority-queue",
3-
"version": "6.2.0",
3+
"version": "6.3.0",
44
"description": "A heap-based implementation of priority queue in javascript with typescript support.",
55
"main": "index.js",
66
"types": "index.d.ts",

src/maxPriorityQueue.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class MaxPriorityQueue<T> {
1111
push(value: T): MaxPriorityQueue<T>;
1212
dequeue(): T;
1313
pop(): T;
14+
remove(cb: (value: T) => boolean): T[];
1415
toArray(): T[];
1516
clear(): void;
1617
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MaxPriorityQueue<T>;

src/maxPriorityQueue.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,32 @@ class MaxPriorityQueue {
7979
return this.dequeue();
8080
}
8181

82+
/**
83+
* Removes all elements that match a criteria in the callback
84+
* @public
85+
* @param {function} cb
86+
* @returns {array}
87+
*/
88+
remove(cb) {
89+
if (typeof cb !== 'function') {
90+
throw new Error('MaxPriorityQueue remove expects a callback');
91+
}
92+
93+
const removed = [];
94+
const dequeued = [];
95+
while (!this.isEmpty()) {
96+
const popped = this.pop();
97+
if (cb(popped)) {
98+
removed.push(popped);
99+
} else {
100+
dequeued.push(popped);
101+
}
102+
}
103+
104+
dequeued.forEach((val) => this.push(val));
105+
return removed;
106+
}
107+
82108
/**
83109
* Returns the number of elements in the queue
84110
* @public

src/minPriorityQueue.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class MinPriorityQueue<T> {
1111
push(value: T): MinPriorityQueue<T>;
1212
dequeue(): T;
1313
pop(): T;
14+
remove(cb: (value: T) => boolean): T[];
1415
toArray(): T[];
1516
clear(): void;
1617
static fromArray<T>(values: T[], getCompareValue?: IGetCompareValue<T>): MinPriorityQueue<T>;

src/minPriorityQueue.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,32 @@ class MinPriorityQueue {
7878
return this.dequeue();
7979
}
8080

81+
/**
82+
* Removes all elements that match a criteria in the callback
83+
* @public
84+
* @param {function} cb
85+
* @returns {array}
86+
*/
87+
remove(cb) {
88+
if (typeof cb !== 'function') {
89+
throw new Error('MinPriorityQueue remove expects a callback');
90+
}
91+
92+
const removed = [];
93+
const dequeued = [];
94+
while (!this.isEmpty()) {
95+
const popped = this.pop();
96+
if (cb(popped)) {
97+
removed.push(popped);
98+
} else {
99+
dequeued.push(popped);
100+
}
101+
}
102+
103+
dequeued.forEach((val) => this.push(val));
104+
return removed;
105+
}
106+
81107
/**
82108
* Returns the number of elements in the queue
83109
* @public

src/priorityQueue.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class PriorityQueue<T> {
1111
push(value: T): PriorityQueue<T>;
1212
dequeue(): T;
1313
pop(): T;
14+
remove(cb: (value: T) => boolean): T[];
1415
toArray(): T[];
1516
clear(): void;
1617
static fromArray<T>(values: T[], compare: ICompare<T>): PriorityQueue<T>;

src/priorityQueue.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,32 @@ class PriorityQueue {
7979
return this.dequeue();
8080
}
8181

82+
/**
83+
* Removes all elements that match a criteria in the callback
84+
* @public
85+
* @param {function} cb
86+
* @returns {array}
87+
*/
88+
remove(cb) {
89+
if (typeof cb !== 'function') {
90+
throw new Error('PriorityQueue remove expects a callback');
91+
}
92+
93+
const removed = [];
94+
const dequeued = [];
95+
while (!this.isEmpty()) {
96+
const popped = this.pop();
97+
if (cb(popped)) {
98+
removed.push(popped);
99+
} else {
100+
dequeued.push(popped);
101+
}
102+
}
103+
104+
dequeued.forEach((val) => this.push(val));
105+
return removed;
106+
}
107+
82108
/**
83109
* Returns the number of elements in the queue
84110
* @public

test/PriorityQueue.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ describe('PriorityQueue', () => {
108108
});
109109
});
110110

111+
describe('remove', () => {
112+
it('remove elements that match a criteria', () => {
113+
const testArr = [20, 30, 40, 50, 80, 90];
114+
const qTest = PriorityQueue.fromArray(testArr.slice(), (a, b) => a - b);
115+
const removed = qTest.remove((n) => [30, 50, 80].includes(n));
116+
expect(removed.sort()).to.eql([30, 50, 80]);
117+
expect(qTest.pop()).to.eql(20);
118+
expect(qTest.pop()).to.eql(40);
119+
expect(qTest.pop()).to.eql(90);
120+
});
121+
});
122+
111123
describe('iterator', () => {
112124
it('allows iterating on queue elements', () => {
113125
const testArr = [20, 30, 40, 50, 80, 90];

0 commit comments

Comments
 (0)