JavaScript对数据进行分组、根据数据值分组、只针对数组、普通函数变为高阶函数、参数归一化

MENU

  • 数据源
  • 低端版本
  • 中端版本(高阶函数)
  • 高级版本(高阶函数+参数归一化)


数据源

let list = [
    { id: 'id_a1', name: 'DuFu', age: 20, sex: 'male' },
    { id: 'id_b2', name: 'LiQingZhao', age: 18, sex: 'female' },
    { id: 'id_c3', name: 'LiBai', age: 26, sex: 'male' },
    { id: 'id_d4', name: 'XinQiJi', age: 30, sex: 'male' },
    { id: 'id_e5', name: 'LinHuiYin', age: 25, sex: 'female' },
    { id: 'id_f6', name: 'MouMouMou', age: 18, sex: 'female' },
    { id: 'id_g7', name: 'HeZhiZhang', age: 26, sex: 'male' }
],
    numArr = [1, 28, 2, 29, 5, 30, 6, 37, 3, 12, 36, 8, 52, 9, 51, 5, 65];

低端版本

function groupBy(arr, propName) {
    const result = {};

    for (const item of arr) {
        const key = item[propName];
        
        if (!result[key]) result[key] = [];

        result[key].push(item);
    }

    return result;
}

console.log(groupBy(list, 'age'));
// {18: Array(2), 20: Array(1), 25: Array(1), 26: Array(2), 30: Array(1)}
console.log(groupBy(list, 'sex'));
// {male: Array(4), female: Array(3)}

这个版本相信大家已看就懂,不多做解释。


中端版本(高阶函数)

function groupBy(arr, generateKey) {
    const result = {};

    for (const item of arr) {
        const key = generateKey(item);
        
        if (!result[key]) result[key] = [];

        result[key].push(item);
    }

    return result;
}

console.log(groupBy(list, item => item.age));
// {18: Array(2), 20: Array(1), 25: Array(1), 26: Array(2), 30: Array(1)}
console.log(groupBy(list, item => item.sex));
// {male: Array(4), female: Array(3)}
console.log(groupBy(list, item => `${item.sex}_${item.age}`));
// {male_20: Array(1), female_18: Array(2), male_26: Array(2), male_30: Array(1), female_25: Array(1)}
console.log(groupBy(numArr, item => item % 2 === 0 ? 'even' : 'odd'));
// {odd: Array(9), even: Array(8)}

仔细观察就不难发现,第二个参数已经不再是普通的字符串了。而是从字符串转变为函数,函数通过调用,把最终分组的形式和依据转交给了调用者。调用者可以根据自己的需求编写传入的分组依据。


高级版本(高阶函数+参数归一化)

function groupBy(arr, generateKey) {
    // 参数归一化(一)
    // if (typeof generateKey === 'string') generateKey = (item) => item[generateKey];

    // 参数归一化(二)
    if (typeof generateKey === 'string') {
        const keyPropertyName = generateKey;

        generateKey = (item) => item[keyPropertyName];
    }

    const result = {};

    for (const item of arr) {
        const key = generateKey(item);

        if (!result[key]) result[key] = [];

        result[key].push(item);
    }

    return result;
}

console.log(groupBy(list, item => item.age));
// {18: Array(2), 20: Array(1), 25: Array(1), 26: Array(2), 30: Array(1)}
console.log(groupBy(list, item => item.sex));
// {male: Array(4), female: Array(3)}
console.log(groupBy(list, item => `${item.sex}_${item.age}`));
// {male_20: Array(1), female_18: Array(2), male_26: Array(2), male_30: Array(1), female_25: Array(1)}
console.log(groupBy(numArr, item => item % 2 === 0 ? 'even' : 'odd'));
// {odd: Array(9), even: Array(8)}
console.log(groupBy(list, 'age'));
// {18: Array(2), 20: Array(1), 25: Array(1), 26: Array(2), 30: Array(1)}
console.log(groupBy(list, 'sex'));
// {male: Array(4), female: Array(3)}

这里主要解释一下参数归一化,意思就是把不同的参数类型转为同一种数据类型。这里是把字符串类型的参数转为函数类型的参数。
参数归一化的第一种方式存在问题,所以使用了第二种方式实现参数归一化。
存在的问题
generateKey的值不会在函数中正确解析。这是因为在箭头函数中,它会捕获最外层的generateKey变量,而不是按照意图解析字符串并使用它作为属性名称。

if (typeof generateKey === 'string') generateKey = (item) => item[generateKey];
if (typeof generateKey === 'string') {
	const keyPropertyName = generateKey;

	generateKey = (item) => item[keyPropertyName];
}

你可能感兴趣的:(web前端,JavaScript,前端,web,javascript,开发语言)