JavaScript如何实现数组按属性分组
作者:一花一world
在JavaScript中,有多种方法可以对数组按属性进行分组。以下是至少6种常见的方法:
6种方法的使用场景和优缺点的简要描述
1.使用reduce()方法
使用场景:适用于需要对数组进行聚合操作的情况,可以自定义聚合逻辑。
优点:灵活性高,可以自定义聚合逻辑;可以同时对多个属性进行分组。
缺点:代码相对复杂,需要熟悉reduce()方法的使用。
2.使用forEach()方法:
使用场景:适用于简单的分组需求,不需要自定义聚合逻辑。
优点:简单易懂,代码量较少。
缺点:无法同时对多个属性进行分组;不支持链式操作。
3.使用map()方法和Object.create(null):
使用场景:适用于需要创建一个纯净的空对象作为分组结果的情况。
优点:可以创建一个没有原型链的空对象,避免可能的属性冲突。
缺点:相对于使用普通对象,性能稍差。
4.使用Map对象:
使用场景:适用于需要对分组结果进行进一步操作的情况,如遍历、删除、更新等。
优点:支持对分组结果进行灵活的操作;可以同时对多个属性进行分组。
缺点:相对于普通对象,Map对象的性能稍差。
5.使用lodash库的groupBy()方法:
使用场景:适用于使用lodash库的项目,或者需要使用其他lodash库的功能。
优点:简单易用,代码量少;lodash库提供了丰富的其他功能。
缺点:引入了额外的库,增加了项目的依赖。
6.使用ES6的Map和箭头函数:
使用场景:适用于需要使用ES6的特性,或者需要对分组结果进行进一步操作的情况。
优点:支持对分组结果进行灵活的操作;可以同时对多个属性进行分组;使用了ES6的特性。
缺点:相对于普通对象,Map对象的性能稍差。
根据具体的需求和项目环境,选择适合的方法可以提高代码的可读性和性能。对于简单的分组需求,可以选择forEach()方法或lodash库的groupBy()方法;对于复杂的分组需求,可以选择reduce()方法、Map对象或ES6的Map和箭头函数。
1.使用reduce()方法封装的方法
这种方法使用reduce()方法来对数组进行迭代,并根据指定的属性值将元素分组。它使用一个空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。
- 首先创建一个空对象,用于存储分组结果。
- 使用for循环遍历数组中的每个元素。
- 在每次迭代中,使用if语句检查当前元素的属性值是否已经存在于分组对象中。
- 如果属性值不存在,就创建一个新的属性,并将当前元素添加到该属性对应的数组中。
- 如果属性值已经存在,就将当前元素添加到该属性对应的数组中。
- 最后返回分组对象。
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByReduce(arr, 'age'); console.log(result);
输出结果:
{
'20': [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Charlie', age: 20, gender: 'male' }
],
'25': [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Eve', age: 25, gender: 'female' }
],
'30': [
{ name: 'David', age: 30, gender: 'male' }
]
}
2.使用forEach()方法封装的方法
这种方法使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。它使用一个空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。
- 使用reduce方法对数组进行迭代,并传入一个初始值为空对象。
- 在每次迭代中,使用初始值作为累加器,并根据当前元素的属性值,将元素添加到相应的属性数组中。
- 最后返回累加器,即分组结果。
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByForEach(arr, 'gender'); console.log(result);
输出结果:
{
female: [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Eve', age: 25, gender: 'female' }
],
male: [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Charlie', age: 20, gender: 'male' },
{ name: 'David', age: 30, gender: 'male' }
]
}
3.使用map()方法和Object.create(null)封装的方法
这种方法使用map()方法对数组进行迭代,并根据指定的属性值将元素分组。它使用Object.create(null)创建一个没有原型的空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。
- 创建一个空的Map对象,用于存储分组结果。
- 使用forEach方法对数组进行迭代。
- 在每次迭代中,根据当前元素的属性值,使用Map对象的get方法获取对应的属性数组。
- 如果属性数组不存在,就创建一个新的属性数组,并将当前元素添加到该数组中。
- 如果属性数组已经存在,就将当前元素添加到该数组中。
- 最后将分组结果转换为普通对象,并返回。
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByMap(arr, 'age'); console.log(result);
输出结果:
{
'20': [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Charlie', age: 20, gender: 'male' }
],
'25': [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Eve', age: 25, gender: 'female' }
],
'30': [
{ name: 'David', age: 30, gender: 'male' }
]
}
4.使用Map对象封装的方法
这种方法使用Map对象来存储分组结果。它使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。在迭代过程中,根据属性值将元素添加到相应的分组中,并使用Map对象的set()方法来保存分组结果。
- 创建一个空的Map对象,用于存储分组结果。
- 使用forEach方法对数组进行迭代。
- 在每次迭代中,使用箭头函数来根据当前元素的属性值,将元素添加到相应的属性数组中。
- 最后将分组结果转换为普通对象,并返回。
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByMapObj(arr, 'gender'); console.log(result);
输出结果:
{
female: [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Eve', age: 25, gender: 'female' }
],
male: [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Charlie', age: 20, gender: 'male' },
{ name: 'David', age: 30, gender: 'male' }
]
}
5.使用lodash库的groupBy()方法封装的方法
这种方法使用lodash库的groupBy()方法来实现分组。它接受一个数组和一个属性名作为参数,并返回一个对象,其中键是属性值,值是具有相同属性值的元素数组。
- 使用lodash库的groupBy方法,传入数组和属性名作为参数。
- groupBy方法会根据属性值将数组元素分组,并返回一个对象,其中键是属性值,值是具有相同属性值的元素数组。
- 返回分组结果
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByLodash(arr, 'age'); console.log(result);
输出结果:
{
'20': [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Charlie', age: 20, gender: 'male' }
],
'25': [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Eve', age: 25, gender: 'female' }
],
'30': [
{ name: 'David', age: 30, gender: 'male' }
]
}
6.使用ES6的Map和箭头函数封装的方法
这种方法使用ES6的Map对象来存储分组结果。它使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。在迭代过程中,根据属性值将元素添加到相应的分组中,并使用Map对象的set()方法来保存分组结果。
- 创建一个空的Map对象,用于存储分组结果。
- 使用forEach方法对数组进行迭代。
- 在每次迭代中,使用箭头函数来根据当前元素的属性值,将元素添加到相应的属性数组中。
- 最后将分组结果转换为普通对象,并返回。
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; const result = groupByMapArrow(arr, 'gender'); console.log(result);
输出结果:
{
female: [
{ name: 'Alice', age: 20, gender: 'female' },
{ name: 'Eve', age: 25, gender: 'female' }
],
male: [
{ name: 'Bob', age: 25, gender: 'male' },
{ name: 'Charlie', age: 20, gender: 'male' },
{ name: 'David', age: 30, gender: 'male' }
]
}
以上是六种不同的方法的详细说明和使用示例。根据需求和个人喜好,可以选择适合的方法来进行分组操作。
7.试着封装起来
以下是将这6种方法封装
function groupBy(arr, prop, method) { switch (method) { case 'reduce': return arr.reduce((result, item) => { const key = item[prop]; if (!result[key]) { result[key] = []; } result[key].push(item); return result; }, {}); case 'forEach': const grouped = {}; arr.forEach(item => { const key = item[prop]; if (!grouped[key]) { grouped[key] = []; } grouped[key].push(item); }); return grouped; case 'map': const grouped = Object.create(null); arr.map(item => { const key = item[prop]; if (!grouped[key]) { grouped[key] = []; } grouped[key].push(item); }); return grouped; case 'mapObj': const grouped = new Map(); arr.forEach(item => { const key = item[prop]; const group = grouped.get(key) || []; group.push(item); grouped.set(key, group); }); return Object.fromEntries(grouped); case 'lodash': const _ = require('lodash'); return _.groupBy(arr, prop); case 'mapArrow': const grouped = new Map(); arr.forEach(item => { const key = item[prop]; const group = grouped.get(key) || []; group.push(item); grouped.set(key, group); }); return Object.fromEntries(grouped); default: return {}; } }
使用示例:
const arr = [ { name: 'Alice', age: 20, gender: 'female' }, { name: 'Bob', age: 25, gender: 'male' }, { name: 'Charlie', age: 20, gender: 'male' }, { name: 'David', age: 30, gender: 'male' }, { name: 'Eve', age: 25, gender: 'female' } ]; console.log(groupBy(arr, 'age', 'reduce')); console.log(groupBy(arr, 'gender', 'forEach')); console.log(groupBy(arr, 'age', 'map')); console.log(groupBy(arr, 'gender', 'mapObj')); console.log(groupBy(arr, 'age', 'lodash')); console.log(groupBy(arr, 'gender', 'mapArrow'));
封装后,可以根据传入的方法名调用相应的分组方法,方便调用和切换不同的分组方法。
到此这篇关于JavaScript如何实现数组按属性分组的文章就介绍到这了,更多相关JavaScript数组分组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!