Home Manual Reference Source

src/nsmallest.js

import {min} from '@iterable-iterator/reduce';
import {sorted} from '@iterable-iterator/sorted';
import {forwardRangeIterator} from '@iterable-iterator/range';
import {iter} from '@iterable-iterator/iter';
import {_zip2} from '@iterable-iterator/zip';
import {reversed} from '@total-order/reversed';

import {keeporder} from './core/index.js';

import heapify from './heapify.js';
import heapreplace from './heapreplace.js';

export default function nsmallest(compare, n, iterable) {
	if (n === 1) {
		const sentinel = {};

		const result = min(compare, iterable, sentinel);

		return result === sentinel ? [] : [result];
	}

	if (iterable.length !== undefined && n >= iterable.length)
		return sorted(compare, iterable);

	const it = iter(iterable);

	const result = Array.from(
		_zip2(forwardRangeIterator(0, n, 1), it),
		([i, elem]) => [elem, i],
	);

	if (result.length === 0) return result;

	const h = heapify(keeporder(reversed(compare)), result);

	let top = result[0][0];

	let order = n;

	for (const elem of it) {
		if (compare(elem, top) < 0) {
			heapreplace(h, [elem, order]);

			top = result[0][0];

			++order;
		}
	}

	return sorted(
		compare,
		Array.from(result, (r) => r[0]),
	);
}