/**
 *
 * @example
 * ```ts
 * const items = [
 *  {name: 'a', classroom: 'c1'},
 *  {name: 'b', classroom: 'c2'},
 *  {name: 'a', classroom: 't0'}
 * ]
 * const counted = countBy(items1, i => i.name);
 * // counted: { a: 2, b: 1}
 * ```
 */
export function countBy(items, key) {
    const count = {};
    items.forEach(item => {
        const k = key(item);
        if (!count[k]) {
            count[k] = 0;
        }
        count[k] += 1;
    });
    return count;
}
/**
 * @example
 * ```ts
 * const items = [{n: 1}, {n: 2}]
 * const max = maxBy(items, i => i.n);
 * // max: {n: 2}
 * ```
 */
export function maxBy(items, value) {
    if (!items.length) {
        return null;
    }
    let maxItem = items[0];
    let max = value(maxItem);
    for (let i = 1; i < items.length; i++) {
        const item = items[i];
        const v = value(item);
        if (v > max) {
            max = v;
            maxItem = item;
        }
    }
    return maxItem;
}
/**
 * Checks if there are at least `n` elements in the array that match the given condition.
 *
 * @param arr - The input array of elements.
 * @param matchFn - A function that takes an element of the array and returns a boolean value
 *                  indicating if the element matches the desired condition.
 * @param n - The minimum number of matching elements required.
 * @returns A boolean value indicating if there are at least `n` matching elements in the array.
 *
 * @example
 * const arr = [1, 2, 3, 4, 5];
 * const isEven = (num: number): boolean => num % 2 === 0;
 * console.log(atLeastNMatches(arr, isEven, 2)); // Output: true
 */
export function atLeastNMatches(arr, matchFn, n) {
    let count = 0;
    for (let i = 0; i < arr.length; i++) {
        if (matchFn(arr[i])) {
            count++;
            if (count >= n) {
                return true;
            }
        }
    }
    return false;
}
/**
 * Groups an array of elements based on a provided key function.
 *
 * @example
 * interface Student {
 *   name: string;
 *   age: number;
 * }
 * const students: Student[] = [
 *   { name: 'Alice', age: 25 },
 *   { name: 'Bob', age: 23 },
 *   { name: 'Cathy', age: 25 },
 * ];
 * const groupedByAge = groupBy(students, (student) => student.age.toString());
 * console.log(groupedByAge);
 * // Output: {
 *  '23': [ { name: 'Bob', age: 23 } ],
 *  '25': [ { name: 'Alice', age: 25 }, { name: 'Cathy', age: 25 } ]
 * }
 */
export function groupBy(arr, key) {
    const result = {};
    for (const item of arr) {
        const groupKey = 
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (typeof key === 'function' ? key(item) : item[key]);
        if (!result[groupKey]) {
            result[groupKey] = [];
        }
        result[groupKey].push(item);
    }
    return result;
}
export function pickArray(target, keys) {
    return keys.reduce((pre, key) => {
        pre.push(target[key]);
        return pre;
    }, []);
}
export function pick(target, keys) {
    return keys.reduce((pre, key) => {
        pre[key] = target[key];
        return pre;
    }, {});
}
export function pickValues(target, keys) {
    return keys.reduce((pre, key) => {
        pre.push(target[key]);
        return pre;
    }, []);
}
export function lastN(target, n) {
    return target.slice(target.length - n, target.length);
}
export function isEmpty(obj) {
    if (Object.getPrototypeOf(obj) === Object.prototype) {
        return Object.keys(obj).length === 0;
    }
    if (Array.isArray(obj) || typeof obj === 'string') {
        return obj.length === 0;
    }
    return false;
}
export function keys(obj) {
    return Object.keys(obj);
}
export function last(iterable) {
    if (Array.isArray(iterable)) {
        return iterable[iterable.length - 1];
    }
    let last;
    for (const item of iterable) {
        last = item;
    }
    return last;
}
export function nToLast(iterable, n) {
    if (Array.isArray(iterable)) {
        return iterable[iterable.length - n];
    }
    const arr = [...iterable];
    return arr[arr.length - n];
}
//# sourceMappingURL=iterable.js.map