thi-ng/umbrella

View on GitHub
packages/transducers/src/sorted-frequencies.ts

Summary

Maintainability
A
55 mins
Test Coverage
import type { Fn } from "@thi.ng/api";
import { identity } from "@thi.ng/compose/identity";
import type { Reducer } from "./api.js";
import { count } from "./count.js";
import { groupByMap } from "./group-by-map.js";
import { $$reduce } from "./reduce.js";

/**
 * Reducer. Similar to {@link frequencies}, but instead of a Map produces an
 * array of `[value, frequency]`-pairs, sorted by the descending number of
 * occurrences of each distinct value.
 *
 * @example
 * ```ts tangle:../export/sorted-frequencies.ts
 * import { filter, sortedFrequencies, transduce } from "@thi.ng/transducers";
 *
 * const input = "hello, world! this transducers-stuff is pretty awesome! :)";
 *
 * const freqs = transduce(
 *   filter(x => /[a-z0-9]/.test(x)),
 *   sortedFrequencies(),
 *   input
 * );
 *
 * console.log(freqs);
 * // [
 * //   [ 's', 6 ], [ 'e', 5 ], [ 't', 5 ], [ 'r', 4 ],
 * //   [ 'l', 3 ], [ 'o', 3 ], [ 'h', 2 ], [ 'w', 2 ],
 * //   [ 'd', 2 ], [ 'i', 2 ], [ 'a', 2 ], [ 'u', 2 ],
 * //   [ 'f', 2 ], [ 'n', 1 ], [ 'c', 1 ], [ 'p', 1 ],
 * //   [ 'y', 1 ], [ 'm', 1 ]
 * // ]
 * ```
 */
export function sortedFrequencies<A>(): Reducer<A, [A, number][]>;
export function sortedFrequencies<A>(src: Iterable<A>): [A, number][];
export function sortedFrequencies<A, B>(
    key: Fn<A, B>
): Reducer<A, [B, number][]>;
export function sortedFrequencies<A, B>(
    key: Fn<A, B>,
    src: Iterable<A>
): Map<B, number>;
export function sortedFrequencies(...args: any[]): any {
    const res = $$reduce(sortedFrequencies, args);
    if (res) return res;
    const [init, complete, reduce] = groupByMap({
        key: args[0] || identity,
        group: count(),
    });
    return <Reducer<any, any>>[
        init,
        (acc) => [...complete(acc)].sort((a, b) => b[1] - a[1]),
        (acc, x) => reduce(acc, x),
    ];
}