javaScript 实用算法(数组分组,数组去重,多条件查询,递归子树,新旧数组对象对比等)在前端开发中,算法不仅能提
在前端开发中,算法不仅能提升代码性能和可维护性,还能帮助开发者高效地解决复杂问题。本文通过具体的 JavaScript 算法案例,详细讲解如何实现数组分组、找出数组对象中 id
的最大值和最小值、多条件模糊查询、数组对象去重、删除特定元素、数组对象排序、递归遍历树形结构、对象筛选以及对比并提取新旧数组对象中不同的元素等常见功能,并加上详细的注释帮助理解。
1. 数组分组(reduce)
描述
将数组按指定键进行分组,生成一个对象,每个键对应一个分组数组。
const products = [
{ id: 1, name: '苹果', category: '水果' },
{ id: 2, name: '香蕉', category: '水果' },
{ id: 3, name: '胡萝卜', category: '蔬菜' },
{ id: 4, name: '西兰花', category: '蔬菜' },
{ id: 5, name: '牛奶', category: '乳制品' }
];
function groupBy(array, key) {
return array.reduce((result, current) => {
const groupKey = current[key]; // 获取当前元素的分组键值
if (!result[groupKey]) result[groupKey] = []; // 如果该键不存在,初始化为一个空数组
result[groupKey].push(current); // 将当前元素添加到对应的分组数组中
return result; // 返回更新后的分组结果
}, {}); // 初始值为空对象
}
const groupedProducts = groupBy(products, 'category');
console.log(groupedProducts); // 打印分组后的结果
/* 输出: { 水果: [ { id: 1, name: '苹果', category: '水果' }, { id: 2, name: '香蕉', category: '水果' } ], 蔬菜: [ { id: 3, name: '胡萝卜', category: '蔬菜' }, { id: 4, name: '西兰花', category: '蔬菜' } ], 乳制品: [ { id: 5, name: '牛奶', category: '乳制品' } ] } */
注释说明
- groupBy 函数:使用
reduce
方法遍历数组,根据传入的key
对元素进行分组,最终返回一个包含多个组的对象。 - result[groupKey] :每次遍历时,检查分组键是否已存在,如果不存在则初始化为空数组,之后将当前项加入对应组。
2. 数组对象去重
描述
从数组中根据id移除重复对象,保留唯一对象。
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' },
{ id: 3, name: 'Charlie' },
{ id: 2, name: 'Bob' }
];
function removeDuplicates(array, key) {
const seen = new Set(); // 使用 Set 记录已出现的键值
return array.filter(item => {
const val = item[key]; // 获取当前元素的键值
if (seen.has(val)) return false; // 如果键值已存在,则跳过此元素
seen.add(val); // 否则,将键值添加到 Set 中,并保留此元素
return true;
});
}
const uniqueUsers = removeDuplicates(users, 'id');
console.log(uniqueUsers); // 打印去重后的数组
注释说明
- 去重逻辑:使用
Set
来存储已经见过的id
值,只有首次出现的元素会被保留,重复的则会被过滤掉。
3. 找出数组对象中 id
最大值和最小值
描述
通过对数组对象按 id
排序,找出 id
的最小值和最大值。
const users = [
{ id: 3, name: 'Charlie' },
{ id: 1, name: 'Alice' },
{ id: 4, name: 'Dave' },
{ id: 2, name: 'Bob' }
];
const sortedUsers = [...users].sort((a, b) => a.id - b.id); // 按 id 升序排序
const minUser = sortedUsers[0]; // 数组第一个元素即为最小 id 的对象
const maxUser = sortedUsers[sortedUsers.length - 1]; // 数组最后一个元素为最大 id 的对象
console.log('最小ID:', minUser); // 输出: { id: 1, name: 'Alice' }
console.log('最大ID:', maxUser); // 输出: { id: 4, name: 'Dave' }
注释说明
- sort 方法:通过
sort
方法对数组进行升序排序,a.id - b.id
表示按id
大小排序。 - minUser 和 maxUser:排序后,第一个元素为最小
id
,最后一个元素为最大id
。
4. 多条件模糊查询
描述
根据多个条件进行模糊查询,忽略字符串大小写,支持部分匹配。
const users = [
{ id: 1, name: 'Alice', role: 'Admin' },
{ id: 2, name: 'bob', role: 'User' },
{ id: 3, name: 'Charlie', role: 'admin' },
{ id: 4, name: 'dave', role: 'User' },
{ id: 5, name: 'Eve', role: 'Guest' }
];
function multiConditionFuzzyFilter(array, conditions) {
return array.filter(item =>
// 遍历每个查询条件,检查是否满足
Object.keys(conditions).every(key => {
const itemValue = item[key]?.toString().toLowerCase(); // 将当前对象的属性值转换为小写
const conditionValue = conditions[key]?.toString().toLowerCase(); // 将查询条件值转换为小写
return itemValue.includes(conditionValue); // 检查属性值是否包含查询条件值
})
);
}
// 模糊查询 role 包含 'admin' 且 name 包含 'a'
const filteredUsers = multiConditionFuzzyFilter(users, { role: 'admin', name: 'a' });
console.log(filteredUsers); // 打印符合条件的对象数组
/* 输出: [ { id: 1, name: 'Alice', role: 'Admin' }, { id: 3, name: 'Charlie', role: 'admin' } ] */
注释说明
- 模糊匹配:
includes
用于检查字符串是否包含指定值,支持部分匹配。 - 忽略大小写:将字符串转为小写,以确保查询结果不受大小写影响。
5. 去除数组对象中 id
为 2 的元素
描述
从数组中删除 id
为特定值的对象。
示例代码
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
{ id: 2, name: 'Bob' },
{ id: 4, name: 'Dave' }
];
function removeById(array, idToRemove) {
return array.filter(item => item.id !== idToRemove); // 过滤出不等于指定 id 的元素
}
const updatedUsers = removeById(users, 2);
console.log(updatedUsers); // 打印移除后的数组
注释说明
- 过滤逻辑:通过
filter
过滤掉id
等于idToRemove
的对象,保留其他元素。
6. 使用递归遍历树形结构
描述
递归遍历树形结构的数据,如组织结构图、文件目录等,执行操作。
const treeData = [ { id: 1, name: '根节点', children: [ { id: 2, name: '子节点1', children: [ { id: 4, name: '子节点1-1', children: [] },
{ id: 5, name: '子节点1-2', children: [] }
]
},
{ id: 3, name: '子节点2', children: [] }
]
}
];
function traverseTree(nodes, callback) {
nodes.forEach(node => {
callback(node); // 对当前节点执行操作
if (node.children && node.children.length > 0) {
traverseTree(node.children, callback); // 如果有子节点,则递归遍历子节点
}
});
}
// 示例:打印所有节点的名称
traverseTree(treeData, node => console.log(node.name));
注释说明
- 递归逻辑:遍历每个节点并递归处理其子节点,使用回调函数对每个节点执行特定操作。
7. 对比新旧数组对象并提取不同元素
描述
通过对比两个数组对象,先使用 JSON.stringify
对比两个数组是否相同,再逐项对比每个子项并提取不同的元素。
const oldUsers = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const newUsers = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bobby' }, // 名字变更
{ id: 4, name: 'Dave' }
];
function arraysEqual(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2); // 通过将数组对象序列化为字符串来比较
}
function findDifferences(arr1, arr2) {
const differences = [];
arr2.forEach(newItem => {
const oldItem = arr1.find(item => item.id === newItem.id); // 查找新数组中的元素是否在旧数组中
if (!oldItem || JSON.stringify(newItem) !== JSON.stringify(oldItem)) {
differences.push(newItem); // 如果新旧元素不同,或者新元素不存在于旧数组中,则将其加入差异数组
}
});
return differences; // 返回不同的元素数组
}
const areArraysEqual = arraysEqual(oldUsers, newUsers); // 判断两个数组是否相同
console.log('数组是否相同:', areArraysEqual);
const differentUsers = findDifferences(oldUsers, newUsers); // 找出不同的元素
console.log('不同的元素:', differentUsers);
注释说明
arraysEqual
函数:使用JSON.stringify
序列化数组对象进行整体对比,判断两个数组是否完全相同。findDifferences
函数:遍历新数组,逐项与旧数组进行对比,找出不同的元素并返回。
总结
通过多个实用的 JavaScript 算法案例,本文展示了如何处理数组和对象的常见问题,并结合详细注释帮助理解代码逻辑。掌握这些算法,不仅能够提高开发效率,还能帮助开发者轻松应对复杂的数据处理场景。
希望这些案例对您有所帮助,欢迎在项目中灵活运用!
转载自:https://juejin.cn/post/7415654362992689167