Skip to content

Commit cdb30b4

Browse files
committed
feat: bump version to 3.0.0 and update README with breaking changes and new features
This release introduces significant changes, including: - `setLimit` and `_applyLimit` methods in the HeapAsync class are now async. - Constructors for Heap and HeapAsync now accept options objects for custom comparison and equality functions. - New `isEqual` property added to both classes. - Enhanced eviction logic to maintain the best N elements in the heap.
1 parent 473f1c3 commit cdb30b4

File tree

19 files changed

+815
-306
lines changed

19 files changed

+815
-306
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ heap vs array: push + top(50) of 100
4343

4444
## Changelog
4545

46+
### 3.0.0
47+
48+
The main breaking changes are that `setLimit` and `_applyLimit` methods of the HeapAsync class are now async, and that setting the `limit` property will NOT apply the limit asynchronously; use the `setLimit` method instead.
49+
50+
- Constructor now accepts an options object, `HeapOptions` and `HeapAsyncOptions`, with the `compare` and `isEqual` options.
51+
- Adds the `isEqual` property to the `Heap` and `HeapAsync` classes to support custom equality functions to override the default equality function.
52+
- Custom comparison callbacks trigger O(n) full scan vs O(log n) average for default equality. Addressing [#669](https://github.com/ignlg/heap-js/issues/669).
53+
- Setting a limit makes the heap evict the worst elements to keep the best N elements. Addressing [#656](https://github.com/ignlg/heap-js/issues/656).
54+
- HeapAsync limit should be set with the `setLimit` method to support async limit application. Setting only the `limit` property will not apply the limit asynchronously.
55+
4656
### 2.7.1
4757

4858
- Optimize loop condition in HeapAsync init method.

dist/heap-js.es5.js

Lines changed: 266 additions & 66 deletions
Large diffs are not rendered by default.

dist/heap-js.umd.js

Lines changed: 266 additions & 66 deletions
Large diffs are not rendered by default.

dist/types/Heap.d.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
export * from './HeapAsync';
22
export type Comparator<T> = (a: T, b: T) => number;
33
export type IsEqual<T> = (e: T, o: T) => boolean;
4+
/**
5+
* Heap configuration options.
6+
*/
7+
export interface HeapOptions<T> {
8+
/**
9+
* Comparison function for heap ordering.
10+
* @default Heap.minComparator
11+
*/
12+
compare?: Comparator<T>;
13+
/**
14+
* Default equality function for indexOf, contains, and remove.
15+
* When provided, these methods use heap-optimized search.
16+
* @default Heap.defaultIsEqual
17+
*/
18+
isEqual?: IsEqual<T>;
19+
}
420
export declare const toInt: (n: number) => number;
521
/**
622
* Heap
723
* @type {Class}
824
*/
925
export declare class Heap<T> implements Iterable<T> {
10-
compare: Comparator<T>;
1126
heapArray: Array<T>;
1227
_limit: number;
28+
isEqual: IsEqual<T>;
29+
compare: Comparator<T>;
1330
/**
1431
* Alias of {@link add}
1532
* @see add
@@ -32,9 +49,9 @@ export declare class Heap<T> implements Iterable<T> {
3249
removeAll: () => void;
3350
/**
3451
* Heap instance constructor.
35-
* @param {Function} compare Optional comparison function, defaults to Heap.minComparator<number>
52+
* @param {Function | HeapOptions} compareOrOptions Optional comparison function or options object
3653
*/
37-
constructor(compare?: Comparator<T>);
54+
constructor(compareOrOptions?: Comparator<T> | HeapOptions<T>);
3855
/**
3956
* Gets children indices for given index.
4057
* @param {Number} idx Parent index
@@ -167,7 +184,7 @@ export declare class Heap<T> implements Iterable<T> {
167184
* Adds an element to the heap. Aliases: {@link offer}.
168185
* Same as: {@link push}(element).
169186
* @param {any} element Element to be added
170-
* @return {Boolean} true
187+
* @return {Boolean} true if added, false if limit exceeded and element not good enough
171188
*/
172189
add(element: T): boolean;
173190
/**
@@ -221,16 +238,16 @@ export declare class Heap<T> implements Iterable<T> {
221238
*/
222239
isEmpty(): boolean;
223240
/**
224-
* Get the index of the first occurrence of the element in the heap (using the comparator).
241+
* Get the index of the first occurrence of the element in the heap.
225242
* @param {any} element Element to be found
226-
* @param {Function} callbackFn Optional comparison function, receives (element, needle)
243+
* @param {Function} callbackFn Optional comparison function, receives (element, needle). Note: Custom callbacks trigger O(n) full scan vs O(log n) average for default equality.
227244
* @return {Number} Index or -1 if not found
228245
*/
229246
indexOf(element: T, callbackFn?: IsEqual<T>): number;
230247
/**
231-
* Get the indexes of the every occurrence of the element in the heap (using the comparator).
248+
* Get the indexes of every occurrence of the element in the heap.
232249
* @param {any} element Element to be found
233-
* @param {Function} callbackFn Optional comparison function, receives (element, needle)
250+
* @param {Function} callbackFn Optional comparison function, receives (element, needle). Note: Custom callbacks trigger O(n) full scan vs optimized heap search for default equality.
234251
* @return {Array} Array of indexes or empty array if not found
235252
*/
236253
indexOfEvery(element: T, callbackFn?: IsEqual<T>): number[];
@@ -357,7 +374,7 @@ export declare class Heap<T> implements Iterable<T> {
357374
*/
358375
iterator(): Iterable<T>;
359376
/**
360-
* Limit heap size if needed
377+
* Limit heap size if needed, removing worst elements to keep best N
361378
*/
362379
_applyLimit(): void;
363380
/**
@@ -422,5 +439,11 @@ export declare class Heap<T> implements Iterable<T> {
422439
* @param list
423440
*/
424441
_topOf(...list: Array<T>): T | undefined;
442+
/**
443+
* Find index of the worst element (for eviction when at limit).
444+
* Worst is always among leaves (second half of array).
445+
* @return {number} Index of worst element, -1 if empty
446+
*/
447+
_worstIndex(): number;
425448
}
426449
export default Heap;

dist/types/HeapAsync.d.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
export type AsyncComparator<T> = (a: T, b: T) => Promise<number>;
22
export type AsyncIsEqual<T> = (e: T, o: T) => Promise<boolean>;
3+
/**
4+
* HeapAsync configuration options.
5+
*/
6+
export interface HeapAsyncOptions<T> {
7+
/**
8+
* Comparison function for heap ordering.
9+
* @default HeapAsync.minComparator
10+
*/
11+
compare?: AsyncComparator<T>;
12+
/**
13+
* Default equality function for contains and remove.
14+
* @default HeapAsync.defaultIsEqual
15+
*/
16+
isEqual?: AsyncIsEqual<T>;
17+
}
318
/**
419
* Heap
520
* @type {Class}
621
*/
722
export declare class HeapAsync<T> implements Iterable<Promise<T>> {
8-
compare: AsyncComparator<T>;
923
heapArray: Array<T>;
1024
_limit: number;
25+
isEqual: AsyncIsEqual<T>;
26+
compare: AsyncComparator<T>;
1127
/**
1228
* Alias of add
1329
*/
@@ -22,9 +38,9 @@ export declare class HeapAsync<T> implements Iterable<Promise<T>> {
2238
poll: () => Promise<T | undefined>;
2339
/**
2440
* Heap instance constructor.
25-
* @param {Function} compare Optional comparison function, defaults to Heap.minComparator<number>
41+
* @param {Function | HeapAsyncOptions} compareOrOptions Optional comparison function or options object
2642
*/
27-
constructor(compare?: AsyncComparator<T>);
43+
constructor(compareOrOptions?: AsyncComparator<T> | HeapAsyncOptions<T>);
2844
/**
2945
* Gets children indices for given index.
3046
* @param {Number} idx Parent index
@@ -157,7 +173,7 @@ export declare class HeapAsync<T> implements Iterable<Promise<T>> {
157173
* Adds an element to the heap. Aliases: `offer`.
158174
* Same as: push(element)
159175
* @param {any} element Element to be added
160-
* @return {Boolean} true
176+
* @return {Boolean} true if added, false if limit exceeded and element not good enough
161177
*/
162178
add(element: T): Promise<boolean>;
163179
/**
@@ -225,10 +241,17 @@ export declare class HeapAsync<T> implements Iterable<Promise<T>> {
225241
*/
226242
get limit(): number;
227243
/**
228-
* Set length limit of the heap.
229-
* @return {Number}
244+
* Set length limit of the heap without eviction.
245+
* Note: Use setLimit() for async limit application with proper eviction.
246+
* @param {Number} _l Limit value
230247
*/
231248
set limit(_l: number);
249+
/**
250+
* Set length limit of the heap with async limit application.
251+
* @param {Number} _l Limit value
252+
* @return {Promise<number>} The limit value
253+
*/
254+
setLimit(_l: number): Promise<number>;
232255
/**
233256
* Top node. Aliases: `element`.
234257
* Same as: `top(1)[0]`
@@ -314,9 +337,9 @@ export declare class HeapAsync<T> implements Iterable<Promise<T>> {
314337
*/
315338
iterator(): Iterable<Promise<T>>;
316339
/**
317-
* Limit heap size if needed
340+
* Limit heap size if needed, removing worst elements to keep best N
318341
*/
319-
_applyLimit(): void;
342+
_applyLimit(): Promise<void>;
320343
/**
321344
* Return the bottom (lowest value) N elements of the heap, without corner cases, unsorted
322345
*
@@ -379,5 +402,11 @@ export declare class HeapAsync<T> implements Iterable<Promise<T>> {
379402
* @param list
380403
*/
381404
_topOf(...list: Array<T>): Promise<T | undefined>;
405+
/**
406+
* Find index of the worst element (for eviction when at limit).
407+
* Worst is always among leaves (second half of array).
408+
* @return {number} Index of worst element, -1 if empty
409+
*/
410+
_worstIndex(): Promise<number>;
382411
}
383412
export default HeapAsync;

docs/assets/navigation.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)