数组常用操作
1. 数组的合并与拆分
- concat() 方法合并两个数组
let arr3 = [1, 2, 3, 4];
let arr4 = ['a', 'b', 'c'];
let res = arr3.concat(arr4); // [1, 2, 3, 4, "a", "b", "c"]
[0].concat(...[1, 2]) //[0, 1, 2]
-
slice() 方法可从已有的数组中返回选定的元素
arr.slice(a, b)
返回一个新的数组,包含从 a 到 b(不包括该元素)的元素。
let arr = [1, 2, 3, 4, 5];
let res = arr.slice(1, 3); // [2, 3]
let arr = [1, 2, 3, 4, 5];
let res = arr.slice(1); // [2, 3, 4, 5]
2.树形结构转换为扁平数组
var tree = [
{
"id":10,
"pid":"-1",
"children":[
{"id":11,"pid":"1","children":[]},
{"id":12,"pid":"1","children":[]}
]
}
];
//方法一:扁平化,但是未去除children属性
function flatten (arr) {
return [].concat(...arr.map(item => [].concat(item, ...flatten(item.children))))
}
flatten(tree)
//[
// {"id":10,"pid":"-1",,"children":[{"id":11,"pid":"1","children":[]},{"id":12,"pid":"1","children":[]}]},
// {"id":11,"pid":"1","children":[]},
// {"id":12,"pid":"1","children":[]}
//]
//方法二:扁平化,并且去除children属性
function treeToList(tree) {
var queen = [];
var out = [];
queen = queen.concat(tree);
while(queen.length) {
var first = queen.shift();
if (first.children) {
queen = queen.concat(first.children)
delete first['children'];
}
out.push(first);
}
return out;
}
treeToList(tree)
//[
// {"id":10,"pid":"-1"},
// {"id":11,"pid":"1"},
// {"id":12,"pid":"1"}
//]
3.扁平数组转换为树形结构
let arr = [
{id: 10, pid: '0'},
{id: 11, pid: '1'},
{id: 12, pid: '1'}
]
let newArr1 = [
{
"id":10,
"pid":"0",
"children":[
{"id":11,"pid":"1","children":[]},
{"id":12,"pid":"1","children":[]}
]
}
]
let newArr2 = [
{
"id":10,
"pid":"0",
"children":[
{"id":11,"pid":"1","children":[],"level":1},
{"id":12,"pid":"1","children":[],"level":1}
],
"level":0
}
]
//将arr转换成newArr1
function listToTree(list) {
var map = {}, node, tree= [], i;
for (i = 0; i < list.length; i ++) {
map[list[i].id] = list[i];
list[i].children = [];
}
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (node.pid !== '0') {
map[node.pid].children.push(node);
} else {
tree.push(node);
}
}
return tree;
}
listToTree(arr);
//将arr转换成newArr2
function listToTreeWithLevel(list, parent, level) {
var out = []
for (var node of list) {
if (node.pid == parent) {
node.level = level;
var children = listToTreeWithLevel(list, node.id, level + 1)
if (children.length) {
node.children = children
}
out.push(node)
}
}
return out
}
listToTreeWithLevel(arr, '-1', 0)
4.数组降维,扁平化处理
const arr = [[1, 2, 3], [4, 5, 6]];
[].concat.apply([], arr); //[1, 2, 3, 4, 5, 6];
//从list1变成list2
let list1 = [
{ a: [{ id: 1, name: "jack" }, { id: 2, name: "bob" }] },
{ a: [{ id: 3, name: "mary" }, { id: 4, name: "tom" }] }
];
let list2 = [
{ id: 1, name: "jack" },
{ id: 2, name: "bob" },
{ id: 3, name: "mary" },
{ id: 4, name: "tom" }
];
let list = list1.map(item => {
return item.a.map(sub => {
return {
id: sub.id,
name: sub.name
};
});
});
let arr = [].concat.apply([],list)
//let arr = [].concat(...list)
//let arr = list.flat() // 存在浏览器兼容问题
5.过滤已选择的项
// availableList: 包含所有可用项的数组
// selectedList: 包含已经选择的项的数组
this.list = this.availableList.filter(item => {
return selectedList.findIndex(chose => {
return chose.id === item.id;
}) <= -1;
});
6.数组去重
6.1. 普通数组
-
利用 Set 数据结构去重
将数组转化为
Set
,Set
自动去除重复的元素,然后再将Set
转化回数组即可。
const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5]
-
利用 reduce() 方法去重
使用
reduce()
方法遍历数组,利用一个空数组存储不重复的元素,每次将不重复的元素push
到数组中。
const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
console.log(uniqueArr); // [1, 2, 3, 4, 5]
-
利用 filter() 方法去重
使用
filter()
方法遍历数组,利用indexOf()
方法判断元素是否在数组中第一次出现的位置,将第一次出现的元素保留下来。
const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = arr.filter((item, index, arr) => {
return arr.indexOf(item) === index;
});
console.log(uniqueArr); // [1, 2, 3, 4, 5]
6.2. 对象数组
- 🌰 假设有一个对象数组,需要根据 name 属性进行去重操作:
const arr = [
{ name: "apple", value: 1 },
{ name: "banana", value: 2 },
{ name: "orange", value: 3 },
{ name: "apple", value: 4 },
{ name: "orange", value: 5 },
];
- 使用 reduce() 方法去重
const uniqueArr = arr.reduce((acc, cur) => {
const index = acc.findIndex((item) => item.name === cur.name);
if (index === -1) {
acc.push(cur);
} else {
acc[index] = cur;
}
return acc;
}, []);
console.log(uniqueArr);
// Output: [
// { name: "apple", value: 4 },
// { name: "banana", value: 2 },
// { name: "orange", value: 5 }
// ]
- 使用 Map 数据结构去重
const map = new Map();
arr.forEach((item) => {
map.set(item.name, item);
});
const uniqueArr = [...map.values()];
console.log(uniqueArr);
// Output: [
// { name: "apple", value: 4 },
// { name: "banana", value: 2 },
// { name: "orange", value: 5 }
// ]
- 使用 filter() 方法去重
const uniqueArr = arr.filter(
(item, index, arr) =>
arr.findIndex((t) => t.name === item.name) === index
);
console.log(uniqueArr);
// Output: [
// { name: "apple", value: 1 },
// { name: "banana", value: 2 },
// { name: "orange", value: 3 }
// ]
-
lodash 库的 uniqBy 方法
如果你的项目中已经使用了
lodash
库,并且有需要按照某个属性或条件去重数组,那么使用uniqBy
方法是一个不错的选择。这个方法接受一个数组和一个用于确定唯一性的属性或条件的函数。
import { uniqBy } from 'lodash';
let uniqueArray = uniqBy(arr, 'name');
console.log(uniqueArray);
//[
// { name: "apple", value: 1 },
// { name: "banana", value: 2 },
// { name: "orange", value: 3 }
// ];
在这个例子中,uniqBy
方法使用对象数组和属性 'id'
,以确保根据 'id'
属性的唯一性进行去重。你可以根据实际需求修改属性或条件。这种方法对于复杂对象数组的去重非常方便。
6.3.不同类型的元素的数组
const arr = [1, 1, '2', 3, 1, 2,
{ name: '张三', id: { n: 1 }},
{ name: '张三', id: { n: 1 }},
{ name: '张三', id: { n: 2 }}
]
function uniqueArray(arr) {
// 创建一个空数组,用于存放去重后的结果
const unique = [];
// 创建一个Map对象,用于记录已经遇到的元素
const map = new Map();
// 遍历输入的数组
for (const item of arr) {
let key;
// 检查item的类型
if (typeof item === 'object') {
// 如果item是一个对象,将其转换为字符串形式
// 注意:这假设对象属性顺序是固定的
key = JSON.stringify(item);
} else {
// 如果item是原始值(如数字或字符串),直接使用它作为键
key = item;
}
// 检查Map中是否已经有了这个键
if (!map.has(key)) {
// 如果没有,将这个键添加到Map中
map.set(key, true);
// 同时将这个唯一的项添加到结果数组中
unique.push(item);
}
}
return unique;
}
uniqueArray(arr);
// 输出:
// [1, "2", 3, 2,
// { name: '张三', id: { n: 1 }},
// { name: '张三', id: { n: 2 }}
// ]
7.多维数组去重
-
使用ES6的new Set()实现去重
使用数组的
flat
方法将多维数组降维为一维数组,参数Infinity
表示不论多少维,都要将数组降维为一维。然后使用ES6
的扩展运算符将Set
转换为数组,并返回去重后的数组。
⚠️需要注意的是,使用
flat
方法可能会对一些较老的浏览器不兼容。
//兼容性不太好的写法:
function uniqueArr(arr) {
return [...new Set(arr.flat(Infinity))]
}
const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]
-
递归方法
适用于任意多维数组,不受数据类型限制。同时,递归方法可以边遍历边去重,减少了内存占用。
function uniqueArr(arr) {
let result = [];
let obj = {};
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (Array.isArray(item)) {
item = uniqueArr(item);
}
if (!obj[item]) {
result.push(item);
obj[item] = true;
}
}
return result;
}
const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [[1, [2, 3], [4, 5]]
// 降维去重:
function uniqueArr(arr) {
let result = [];
let obj = {};
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (Array.isArray(item)) {
item = uniqueArr(item);
}
// 如果是数组,将其扁平化并去除重复元素
if (Array.isArray(item)) {
for (let j = 0; j < item.length; j++) {
let subItem = item[j];
if (!obj[subItem]) {
result.push(subItem);
obj[subItem] = true;
}
}
} else {
// 如果是基本类型,直接去除重复
if (!obj[item]) {
result.push(item);
obj[item] = true;
}
}
}
return result;
}
const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]
-
将多维数组降维后再去重
适用于需要对大规模数据进行去重操作的场景,因为可以利用
Set
数据结构去除数组中的重复项,从而提高去重效率。但是,这种方法需要将多维数组降维为一维数组,会占用更多的内存。
// 将数组降维
function resetArray(arr, newArr){
arr.forEach(item => {
if (toString.call(item) === "[object Array]") {
resetArray(item, newArr);
} else {
newArr.push(item);
}
})
}
// 将数组去重
function uniqueArr(arr) {
var newArr = [];
resetArray(arr, newArr);
console.log([...new Set(newArr)]);
}
const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]
8.求数组对象的交集
const arr1 = [
{ name: 'name1', id: 1 },
{ name: 'name2', id: 2 },
{ name: 'name3', id: 3 }
];
const arr2 = [
{ name: 'name1', id: 1 },
{ name: 'name4', id: 4 },
{ name: 'name5', id: 5 }
];
const res = arr1.filter(item => arr2.findIndex(chose => chose.id === item.id) > -1)
// 输出: [
// { name: 'name1', id: 1 }
// ]
9.求数组对象的并集
const arr1 = [
{ name: 'name1', id: 1 },
{ name: 'name2', id: 2 },
{ name: 'name3', id: 3 }
];
const arr2 = [
{ name: 'name1', id: 1 },
{ name: 'name4', id: 4 },
{ name: 'name5', id: 5 }
];
// 两个数组合并,并去重
// 方法一:
const res1 = arr1.concat(arr2.filter(item => arr1.findIndex(chose => chose.id == item.id) == -1))
// 方法二:
const obj = [];
const res2 = arr1.concat(arr2).reduce(function (prev, cur, index, arr) {
obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);
return prev;
}, []);
// 输出: [
// { name: 'name1', id: 1 },
// { name: 'name2', id: 2 },
// { name: 'name3', id: 3 },
// { name: 'name4', id: 4 },
// { name: 'name5', id: 5 }
// ]
10.求数组对象的差集
const arr1 = [
{ name: 'name1', id: 1 },
{ name: 'name2', id: 2 },
{ name: 'name3', id: 3 }
];
const arr2 = [
{ name: 'name1', id: 1 },
{ name: 'name4', id: 4 },
{ name: 'name5', id: 5 }
];
// 取差集 arr1相对于arr2所没有的
const res1 = arr1.filter(item1 => !arr2.find(item2 => item1.id == item2.id))
// 或者使用 some:
// const res1 = arr1.filter(item1 => !arr2.some(item2 => item1.id === item2.id));
// 输出:[
// { name: 'name2', id: 2 },
// { name: 'name3', id: 3 }
// ]
// 取差集 arrB相对于arrA所没有的
const res2 = arr2.filter(item2 => !arr1.find(item1 => item1.id == item2.id))
// 输出:[
// { name: 'name4', id: 4 },
// { name: 'name5', id: 5 }
// ]
11.树数据字段映射
- 使用场景:数据格式是树形层级的 但字段对应属性不是想要的
// data 原始树形数据
// map 字段映射对象 例子:{value: 'code', label: 'name', children: 'child'}
treeDataMapping (data, map) {
const result = [];
// 遍历 tree
data.forEach(item => {
// 读取 map 的键值映射
const value = item[map.value];
const label = item[map.label];
let children = item[map.children];
// 如果有子节点,递归
if ( children ) {
children = this.treeDataMapping(children, map);
}
result.push({
value,
label,
children
});
});
return result;
}
// 举例
const originalTreeData = [
{
id: 1,
name: "节点1",
code: "A01",
child: [
{
id: 2,
name: "子节点1.1",
code: "A01-1",
child: [
{
id: 4,
name: "子节点1.1.1",
code: "A01-1-1",
},
],
},
{
id: 3,
name: "子节点1.2",
code: "A01-2",
},
],
},
{
id: 5,
name: "节点2",
code: "A02",
},
];
const fieldMap = {
value: 'code',
label: 'name',
children: 'child',
};
treeDataMapping (originalTreeData, fieldMap)
// 输出: [
// {
// value: 'A01',
// label: '节点1',
// children: [
// {
// value: 'A01-1',
// label: '子节点1.1',
// children: [
// {
// value: 'A01-1-1',
// label: '子节点1.1.1',
// children: []
// }
// ]
// },
// {
// value: 'A01-2',
// label: '子节点1.2',
// children: []
// }
// ]
// },
// {
// value: 'A02',
// label: '节点2',
// children: []
// }
// ]
12.查找一个节点的所有父节点
- 查找一个节点的所有父节点(返回的数据包含本身)
// array 原始树形数据
// id 子节点id
familyTree (array, id) {
let result = [];
let flat = true;
let forFn = (arr, value) => {
arr.forEach(item => {
if ( !flat ) return;
result.push(item['value']);
if ( item['value'] === value ) {
flat = false;
} else if ( item['children'] ) {
forFn(item['children'], value);
} else {
result.pop();
}
});
if ( flat ) result.pop();
};
forFn(array, id);
return result;
}
// 举例
const familyTreeArray = [
{
value: 'Grandfather',
children: [
{
value: 'Father',
children: [
{ value: 'Me', children: [] },
{ value: 'Brother', children: [] }
]
},
{
value: 'Uncle',
children: [
{ value: 'Cousin', children: [] }
]
}
]
},
{
value: 'Great Grandfather',
children: []
}
];
familyTree(familyTreeArray, 'Me')
// ['Grandfather', 'Father', 'Me']
13.写一个获取数组的最大值、最小值的方法
-
使用
Math.max.apply()
和Math.min.apply()
方法来获取数组中的最大值和最小值。 -
这两个方法都需要传递一个数组作为第二个参数,其中数组的元素将作为
Math.max()
或Math.min()
方法的参数。由于Math.max()
和Math.min()
方法不能直接接受数组作为参数,因此我们需要使用Function.prototype.apply()
方法将数组元素作为单独的参数传递给这两个方法。
var arr1 = [25,62,91,78,34,62];
var arr2 = [27,64,90,78,34,62];
var max = Math.max.apply(null, arr1);
var min = Math.min.apply(null, arr2);
console.log(max); // 91
console.log(min); // 27
14.数组实现分类统计
🌰 将水果数组中同类的水果合并为一条并求出总数
const fruits = [
{ name: 'apple', value: 1 },
{ name: 'apple', value: 2 },
{ name: 'banana', value: 2 },
{ name: 'banana', value: 3 }
];
-
方法一: 用reduce()方法进行统计
使用
reduce()
方法对水果数组进行遍历和合并操作。在回调函数中,我们定义了一个累加器acc
和当前元素curr
,并使用一个循环遍历累加器中已有的水果类型。如果当前元素的水果类型已存在于累加器中,则将其数量累加;否则,将当前元素添加到累加器中。最后,我们将累加器中的水果类型和数量转换为一个包含对象的数组,并将其打印到控制台。
const result = fruits.reduce(function(acc, curr) {
var found = false;
for (var i = 0; i < acc.length; i++) {
if (acc[i].name === curr.name) {
acc[i].value += curr.value;
found = true;
break;
}
}
if (!found) {
acc.push({ name: curr.name, value: curr.value });
}
return acc;
}, []);
console.log(result);
// 输出:[
// { name: 'apple', value: 3 },
// { name: 'banana', value: 5 }
// ]
- 方法二:使用对象进行归类和统计
// 定义空数组,用于存储统计数据
const fruitTotal = []; // 存最终数据结果
// 数据按照水果名称进行归类
const nameContainer = {}; // 针对键name进行归类的容器
fruits.forEach(item => {
nameContainer[item.name] = nameContainer[item.name] || [];
nameContainer[item.name].push(item);
});
console.log(nameContainer); // 按照水果名称归类完成:{ apple: Array(2), banana: Array(2) }
// 统计不同种类水果的数量
const fruitName = Object.keys(nameContainer); // 获取水果种类:["apple", "banana"]
fruitName.forEach(nameItem => {
let count = 0;
nameContainer[nameItem].forEach(item => {
count += item.value; // 遍历每种水果中包含的条目计算总数
});
fruitTotal.push({'name': nameItem, 'total': count});
});
console.log(fruitTotal);
// 输出:[
// { name: "apple", total: 3 },
// { name: "banana", total: 5 }
// ]
使用reduce()方法进行统计
优点:
代码量相对较少,逻辑清晰,易于理解。
使用了
ES6
的特性,具有一定的现代化。缺点:
- 使用
reduce()
方法需要有一定的函数式编程经验。- 由于使用了
reduce()
方法,可能不够直观,需要花费一些时间去理解代码的实现。使用对象进行归类和统计
优点:
对象直接进行归类和统计,直观易懂,代码易于理解。
可以避免使用
reduce()
方法时可能出现的问题,如NaN
的问题。可以对每一种水果进行更复杂的操作,如计算平均值等。
缺点:
- 代码量相对较多,可能不太直观,需要更多的时间去理解代码的实现。
- 由于使用了对象进行归类和统计,可能会占用较多的内存空间。
15.对象数组根据key重新分组成新的对象数组
- 方法一
const arr = [
{ "id": "1001", "name": "值1", "value": "111" },
{ "id": "1001", "name": "值1", "value": "11111" },
{ "id": "1002", "name": "值2", "value": "25462" },
{ "id": "1002", "name": "值2", "value": "23131" },
{ "id": "1002", "name": "值2", "value": "2315432" },
{ "id": "1003", "name": "值3", "value": "333333" }
];
function getArrWithKey(originalArr, field) {
const tempArr = [];
const endData = [];
for (let i = 0; i < originalArr.length; i++) {
if (tempArr.indexOf(originalArr[i][field]) === -1) {
endData.push({
[field]: originalArr[i][field],
data: [originalArr[i]]
});
tempArr.push(originalArr[i][field]);
} else {
for (let j = 0; j < endData.length; j++) {
if (endData[j][field] == originalArr[i][field]) {
endData[j].data.push(originalArr[i]);
break;
}
}
}
}
return endData // 最终输出
}
getArrWithKey(arr, 'name');
// [
// {
// "name": "值1",
// "data": [
// {"id": "1001","name": "值1", "value": "111"},
// {"id": "1001","name": "值1", "value": "11111"}
// ]
// },
// {
// "name": "值2",
// "data": [
// {"id": "1002", "name": "值2", "value": "25462"},
// { "id": "1002", "name": "值2", "value": "23131"},
// {"id": "1002","name": "值2","value": "2315432"}
// ]
// },
// {
// "name": "值3",
// "data": [
// {"id": "1003", "name": "值3","value": "333333"}
// ]
// }
// ]
-
方法二
使用
JavaScript
的reduce()
方法将对象数组根据特定的键重新分组为新的对象数组。
const arr = [
{id: 1, name: 'John', group: 'A'},
{id: 2, name: 'Jane', group: 'B'},
{id: 3, name: 'Jim', group: 'A'}
];
const result = Object.entries(arr.reduce((acc, curr) => {
(acc[curr.group] = acc[curr.group] || []).push(curr);
return acc;
}, {})).map(([key, value]) => {
return { group: key, members: value };
});
console.log(result);
//[
// {
// group: 'A',
// members: [
// {id: 1, name: 'John', group: 'A'},
// {id: 3, name: 'Jim', group: 'A'}
// ]
// },
// {
// group: 'B',
// members: [
// {id: 2, name: 'Jane', group: 'B'}
// ]
// }
//]
16.将具有length属性的对象转成数组
-
将函数的实际参数转换成数组的方法:
-
方法一:
var args = Array.prototype.slice.call(arguments)
; -
方法二:
var args = [].slice.call(arguments, 0)
;
-
let toArray = function(s){
//try语句允许我们定义在执行时进行错误测试的代码块。
//catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
try{
return Array.prototype.slice.call(s);
} catch(e){
const arr = [];
for(let i = 0,len = s.length; i < len; i++){
//arr.push(s[i]);
arr[i] = s[i]; //据说这样比push快
}
return arr;
}
}
17. 移除数组中的某一项
function remove (arr, item) {
if (arr.length) {
const index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1)
}
}
}
18. toArray 把类数组转成真正的数组
-
需求: 把类数组转换成数组,支持从任意位置开始,默认从
0
开始。在
JavaScript
中,有些对象看起来像数组,但是它们没有Array
原型链上的方法。这些对象被称为类数组对象。 -
方法:
如果需要对类数组对象进行数组的操作,需要将其转换为真正的数组。可以使用
JavaScript
中的Array.from()
方法或者Array.prototype.slice.call()
方法将类数组对象转换为数组。
function toArray(list, start = 0) {
const arr = Array.prototype.slice.call(list, start);
return JSON.parse(JSON.stringify(arr));
}
const arrayLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
const arr = toArray(arrayLike, 1);
console.log(arr); // 输出:["bar", "baz"]
// 类数组对象中的元素是对象
const arrayLike1 = { 0: {name: 'foo'}, 1: {name: 'bar'}, length: 2 };
const arr1 = toArray(arrayLike, 0);
console.log(arr1); // 输出:[{name: "foo"}, {name: "bar"}]
需要注意的是,如果类数组对象中的元素包含函数、循环引用等特殊类型的数据,会出现序列化失败的情况。
-
方法二
使用数组的下标访问方式,将类数组对象转换为真正的数组。
与使用
Array.prototype.slice.call()
方法或者Array.from()
方法相比,该函数的代码更加简洁明了。同时,该函数不需要将方法附加到原型链上,也不需要使用call
或者apply
方法调用。
function toArray (list, start = 0) {
let i = list.length - start; // 计算要转换的元素数量 i
const ret = new Array(i); // 创建一个空数组 ret
// 使用 while 循环将类数组对象中的元素复制到新数组中,最终返回新数组 ret
while (i--) {
ret[i] = list[i + start];
}
return ret
}
// 例子:
function fn(){
const arr1 = toArray(arguments);
console.log(arr1); // [1, 2, 3, 4, 5]
const arr2 = toArray(arguments, 2);
console.log(arr2); // [3, 4, 5]
}
fn(1,2,3,4,5);
⚠️需要注意的是,如果类数组对象中的元素是对象,使用该方法只是将对象的引用复制到新的数组中,如果需要对数组中的元素进行深拷贝,需要使用其他方法。
19.数组对象转对象
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
];
const obj = {};
arr.forEach(item => {
obj[item.name] = item.age;
});
console.log(obj);
// 输出:{ Alice: 25, Bob: 30, Charlie: 35 }
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
];
const obj = arr.reduce((result, item) => {
result[item.name] = { ...item };
delete result[item.name].name;
return result;
}, {});
console.log(obj);
// 输出:{
// Alice: { age: 25 },
// Bob: { age: 30 },
// Charlie: { age: 35 }
// }
20.将数组中指定的元素挪到第一位
20.1. 普通数组
const arr = [1,2,3,4]
const key = 3
// 方法一:
for (var i = 0; i < arr.length; i++) {
if (arr[i] === key) {
arr.splice(i, 1); // 先把符合条件的数据从当前数组中删除
break;
}
}
arr.unshift(key); // 通过unshift函数把符合要求的数据放到第一位
console.log(arr); // 输出:[3, 1, 2, 4]
// 方法二:
const index = arr.indexOf(key); // 使用 indexOf 方法获取 key 在数组 arr 中的索引
if (index > 0) {
arr.splice(index, 1);
arr.splice(0, 0, x);
}
console.log(arr); // 输出:[3, 1, 2, 4]
20.2. 对象数组
const arr = [
{id: 1, name: 'Alice'},
{id: 2, name: 'Bob'},
{id: 3, name: 'Charlie'},
{id: 4, name: 'David'},
{id: 5, name: 'Emily'}
];
const key = 3
let obj = {}; //声明一个对象保存符合要求的数据
// 方法一:
arr.forEach((item,index)=>{
if(item.id === key){
obj = item;
arr.splice(index,1) //先把符合条件的数据从当前数组中删除
return;
}
})
arr.unshift(obj); //通过unshift函数把符合要求的数据放到第一位
console.log(arr);
// 方法二:
// 使用 findIndex 方法查找具有指定属性值的元素的索引
const index = arr.findIndex(item => item.id === key);
if (index > 0) {
arr.splice(index, 1);
arr.splice(0, 0, x);
}
console.log(arr);
// 输出:[
// {
// "id": 3,
// "name": "Charlie"
// },
// {
// "id": 1,
// "name": "Alice"
// },
// {
// "id": 2,
// "name": "Bob"
// },
// {
// "id": 4,
// "name": "David"
// },
// {
// "id": 5,
// "name": "Emily"
// }
// ]
21.将两个数组合并成一个数组对象
let arr1 = [10, 11, 12]
let arr2 = ['a', 'b', 'c']
let newArr = arr1.map((age, i) => ({age, name: arr2[i]}))
console.log(newArr)
// 输出:[{age: 10, name: 'a'}, {age: 11, name: 'b'}, {age: 12, name: 'c'}]
22.判断数组中的每一层对象的某一个字段属性值不能为空
-
这种操作一般用来操作列表,提交数据时需要判断某一个字段不能为空等条件。
-
用
every
,some
遍历数组,区别:every
只要有一项不满足条件都返回false
,some
有一项满足都会返回true
。 -
every方法
function checkFieldNotEmpty(arr, fieldName) {
return arr.every(obj => obj?.[fieldName]);
}
- some方法
function checkFieldNotEmpty(arr, fieldName) {
return arr.some(obj => !obj?.[fieldName]);
}
const arr = [
{ name: 'Alice', age: 18 },
{ name: 'Bob', age: null },
{ name: 'Charlie', age: 25 },
];
const fieldName = 'age';
const result = checkFieldNotEmpty(arr, fieldName);
console.log(result); // 输出 true,因为数组中第二个元素的 age 属性值为空
⚠️需要注意的是,使用
every
和some
方法时需要保证数组中的每个元素都具有指定的属性,否则在获取不存在的属性时会出现错误。可以通过使用JavaScript
的可选链操作符?.
来避免这种错误,可选链操作符可以在对象属性不存在时直接返回undefined
,而不会导致错误。
转载自:https://juejin.cn/post/7360856203839111219