# 数组相关

两个数组的增删改查以及其他处理

# 基础数组功能一网打尽

[1,2,3].length; //? 3
[1,2,3].push(4);//?[1,2,3,4]*
[1,2,3].unshift(0);//?[0,1,2,3] *
[1,2,3].pop();//?[1,2] *
[1,2,3].shift();//?[2,3] *
[1,2,3].at(2);//? 3
[1,2,3].indexof(3);//? 2
[1,2,3].includes(3);//? true
[1,2,3].map((num)=> Math.pow(num,2));//?[1,4,9]
[1,2,3].filter((num)=> num % 2);//? [1,3]
[1,2,3].every((num)=> num >1);//? false
[1,2,3].some((num)=> num == 3);//? true
[1,2,3].fill(10);//? [10,10,10]
[1,2,3].reduce((acc,num)=> acc + num,0);//?6
[1,2,3].concat([4,5]);//? [1,2,3,4,5]
[1,2,3].reverse();//? [3,2,1]
[2,1,3].sort();//? [1,2,3]
[1,2,3].join('-');//? 1-2-3
[1,2,[3]].flat(); //? [1,2,3]
[1,2,3].find((num,i)=> i === 1);//? 2
[1,2,3].findIndex((num)=> num === 2);//? 1
[1,2,3].tostring();//? 1,2,3
[1,2,3].slice(1,3);//? [2,3]
[1,4].splice(1,0,2,3);//?[1,2,3,4] *
Array.isArray("[1,2,3]");//? false
Array.from("123");//?['1','2','3']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 从阵列中删除重复项


let array = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let list = array.filter((x, i, a) => a.indexOf(x) == i);
//[2, 1, 5, 6, 7, 8, 9, 10]

set 方法


let array = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let setuniq = [...new Set(array)];
//[2, 1, 5, 6, 7, 8, 9, 10]

# 从对象数组中删除重复项


let filteruniquebyID = users.filter(
    (v, i, a) => a.findIndex(t => t.id === v.id) === i
);
//[{"id":1,"name":"ted"},{"id":3,"name":"sara"},{"id":4,"name":"test"},{"id":5,"name":"abc"}]

我们可以使用此代码检查具有多个属性的唯一数据


let filteruniquebyIDName = users.filter(
    (v, i, a) => a.findIndex(t => t.id === v.id || t.name === v.name) === i
);
//[{"id":1,"name":"ted"},{"id":3,"name":"sara"},{"id":4,"name":"test"},{"id":5,"name":"abc"}]

使用 set


let set1 = Array.from(
users.reduce((m, t) => m.set(t.id, t), new Map()).values()
);
//[{"id":1,"name":"bob"},{"id":3,"name":"sara"},{"id":4,"name":"test"},{"id":5,"name":"abc"}]

# 数组中查找一个项目


console.log(array.includes(2)); // returns true

every:此方法测试数组中的所有元素是否通过提供的功能实现的测试


let testevery1 = array.every(val=> val>3); //false

some:此方法测试数组中的至少一个元素是否通过了由提供的函数实现的测试



let testsome1 = array.some(val=> val>3); //true

findIndex:此方法返回满足提供的测试功能的数组中第一个元素的索引


let  testindex = array.findIndex(val => val > 1);
//0

find:此方法返回提供的数组中满足提供的测试功能的第一个元素的值


let testfind = array.find(el => (el > 2));
//5

filter:此方法创建一个新数组,其中所有元素都通过了由提供的功能实现的测试


let testfilter1 = array.filter(val=> val>3);
//[5, 6, 7, 8, 9, 9, 10]

map:此方法创建一个新数组,其中填充了对调用数组中每个元素调用提供的函数的结果



let val = [];
array.map(item => { if(item >= 3) val.push(item); });
//[5, 6, 7, 8, 9, 9, 10]

# 在对象数组中找到一个项目

every:此方法测试数组中的所有元素是否通过提供的功能实现的测试


let testevery2 = users.every(val=> val.id>3);
//false

some:此方法测试数组中的至少一个元素是否通过了提供的功能实现的测试


let testsome2 = users.some(val=> val.id>3); //true

findIndex:此方法返回满足提供的测试功能的数组中第一个元素的索引。否则,它返回-1,表明没有任何元素通 过测试


let  testindex2 = users.findIndex(val => val.id > 1);
//3

find:此方法返回提供的数组中满足提供的测试功能的第一个元素的值



let testfind2 = users.find(el => (el.id > 2));
//{"id":3,"name":"sara"}

filter:此方法创建一个新数组,其中所有元素都通过了由提供的功能实现的测试


let testfilter2 = users.filter(val=> val.id>3);

map:此方法创建一个新数组,其中填充了对调用数组中每个元素调用提供的函数的结果


let val2 = [];
users.map(item => { if(item.id >= 3) val2.push(item); });

# 对数组项排序


const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

简单排序


let data = [{
        id: "3",
        city: "toronto",
        state: "TR",
        zip: "75201",
        price: "123451"
    },
    {
        id: "1",
        city: "anand",
        state: "AN",
        zip: "94210",
        price: "345678"
    },
    {
        id: "5",
        city: "sudbury",
        state: "SB",
        zip: "00110",
        price: "789045"
    }
];
let sorttest2 = data.sort((a, b) => (a.id < b.id ? -1 : Number(a.id > b.id)));console.log("sort test 2 ", sorttest2);
//output
{
    "id": "1",
    "city": "anand",
    "state": "AN",
    "zip": "94210",
    "price": "345678"
}, {
    "id": "3",
    "city": "toronto",
    "state": "TR",
    "zip": "75201",
    "price": "123451"
}, {
    "id": "5",
    "city": "sudbury",
    "state": "SB",
    "zip": "00110",
    "price": "789045"
}]

用多个字段排序


let sorttest4 = data.sort(function(left, right) {
    var city_order = left.city.localeCompare(right.city);
    var price_order = parseInt(left.price) - parseInt(right.price);
    return city_order || -price_order;
});
//output
[{
    "id": "1",
    "city": "anand",
    "state": "AN",
    "zip": "94210",
    "price": "345678"
}, {
    "id": "5",
    "city": "sudbury",
    "state": "SB",
    "zip": "00110",
    "price": "789045"
}, {
    "id": "3",
    "city": "toronto",
    "state": "TR",
    "zip": "75201",
    "price": "123451"
}]

对日期数组进行排序


let isDescending = false; //set to true for Descending
let dates = ["1/7/2021", "1/6/2021", "8/18/2020", "8/6/2020"];
let sorteddates = dates.sort((a, b) => isDescending ? new Date(b).getTime() - new Date(a).getTime() : new Date(a).getTime() - new Date(b).getTime());
console.log(sorteddates);
//["8/6/2020", "8/18/2020", "1/6/2021", "1/7/2021"]

# 从阵列中删除一个项目

pop:此方法从数组中删除最后一个元素并返回该元素。此方法更改数组的长度


let arraypoptest = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let testpop = arraypoptest.pop();
console.log("array pop", testpop,"-", arraypoptest);
//10 - [2, 1, 2, 5, 6, 7, 8, 9, 9];

shift:此方法从数组中删除第一个元素并返回该删除的元素。此方法更改数组的长度


let arrayshifttest = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let testshift = arrayshifttest.shift();
console.log("array shift", testshift,"-", arrayshifttest);
//2 - [1, 2, 5, 6, 7, 8, 9, 9, 10]

slice:此方法将数组的一部分的浅表副本返回到一个新的数组对象中,该对象选自 startto end(end 不包括) ,其中 startandend 表示该数组中各项的索引。原始数组将不会被修改


let arrayslicetest = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let testslice = arrayslicetest.slice(0, 3);
console.log("array slice", testslice, arrayslicetest); 
//not changed original array
//[2, 1, 2] - [2, 1, 2, 5, 6, 7, 8, 9, 9, 10]

splice:此方法通过删除或替换现有元素和/或在适当位置添加新元素来更改数组的内容


let arraysplicetest = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let testsplice = arrayslicetest.splice(0, 3);
//[2, 1, 2]

filter:此方法创建一个新数组,其中所有元素都通过了由提供的功能实现的测试


let testarr = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let testarr2 = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
let filtered = testarr.filter(function(value, index, arr) {
    return value > 5;
});
let filtered2 = testarr2.filter(item => item !== 2);
console.log("filter example 1", filtered);
//[6, 7, 8, 9, 9, 10]
console.log("filter example 2", filtered2);
//[1, 5, 6, 7, 8, 9, 9, 10]

//过滤并去除多个值
let forDeletion = [2, 3, 5];
let mularr = [1, 2, 3, 4, 5, 3];
mularr = mularr.filter(item => !forDeletion.includes(item));
console.log("multiple value deletion with filter", mularr);
//[1, 4]

delete 运算符:JavaScript delete 从对象中删除属性;如果不再保存对相同属性的引用,则最终将自动释放该 引用


let ar = [2, 1, 2, 5, 6, 7, 8, 9, 9, 10];
delete ar[4]; // delete element with index 4
console.log(ar);
//[2, 1, 2, 5, undefined, 7, 8, 9, 9, 10]

# 从对象数组中删除一个项目

pop:此方法从数组中删除最后一个元素并返回该元素。此方法更改数组的长度


let users1 = [{
    id: 1,
    name: "ted"
}, {
    id: 2,
    name: "mike"
}, {
    id: 3,
    name: "bob"
}, {
    id: 4,
    name: "sara"
}];
let testpop1 = users1.pop();
console.log(
    "array of objects pop",
    JSON.stringify(testpop1),"-"
    JSON.stringify(users1)
);
//{"id":4,"name":"sara"} - [{"id":1,"name":"ted"},{"id":2,"name":"mike"},{"id":3,"name":"bob"}]

shift:此方法从数组中删除第一个元素并返回该删除的元素。此方法更改数组的长度


let users2 = [
{ id: 1, name: "ted" },
{ id: 2, name: "mike" },
{ id: 3, name: "bob" },
{ id: 4, name: "sara" }
];
let testshift1 = users2.shift();
console.log("array of objects shift", JSON.stringify(testshift1),"-", JSON.stringify(users2));
//{"id":1,"name":"ted"} - [{"id":2,"name":"mike"},{"id":3,"name":"bob"},{"id":4,"name":"sara"}]

slice:此方法将数组的一部分的浅表副本返回到一个新的数组对象中,该对象选自 startto end(不包括 end) ,其中 startandend 表示该数组中各项的索引。原始数组将不会被修改



let users3 = [
{ id: 1, name: "ted" },
{ id: 2, name: "mike" },
{ id: 3, name: "bob" },
{ id: 4, name: "sara" }
];
let testslice1 = users3.slice(0, 3);
console.log("array of objects slice", JSON.stringify(testslice1));
//not changed original array
//[{"id":1,"name":"ted"},{"id":2,"name":"mike"},{"id":3,"name":"bob"}]

splice:此方法通过删除或替换现有元素和/,或者在适当位置添加新元素来更改数组的内容


let users4 = [
{ id: 1, name: "ted" },
{ id: 2, name: "mike" },
{ id: 3, name: "bob" },
{ id: 4, name: "sara" }
];
let testspice1 = users3.splice(0, 3);
console.log("array of objects splice", JSON.stringify(testsplice));
//[{"id":1,"name":"ted"},{"id":2,"name":"mike"},{"id":3,"name":"bob"}

filter:此方法创建一个新数组,其中所有元素都通过了由提供的功能实现的测试


let users7 = [
{ id: 1, name: "ted" },
{ id: 2, name: "mike" },
{ id: 3, name: "bob" },
{ id: 4, name: "sara" }
];
let filterObj = users7.filter(item => item.id !== 2);
console.log("filter example array of objects", filterObj);
//[{"id":1,"name":"ted"},{"id":3,"name":"bob"},{"id":4,"name":"sara"}]

# 从数组中给定的字符串中查找字符数

字符串匹配方法


const test1 = ("atit patel".match(/a/g)||[]).length
console.log(test1); //2

拆分方法


const test2 ="atit patel".split("a").length-1
console.log(test2); //2

indexOf 方法


let  stringsearch = "a" ,str = "atit patel";
for(var count=-1,index=-2; index != -1; count++,index=str.indexOf(stringsearch,index+1) );
console.log(count); //2

filter 方法


const mainStr = 'atit patel';
const test3 = [...mainStr].filter(l => l === 'a').length;
console.log(test3); //2

reduce 方法


const mainStr1 = 'atit patel';
const test4 = [...mainStr1].reduce((a, c) => c === 'a' ? ++a : a, 0);
console.log(test4); //2

# 从数组中给定的字符串中查找每个字符的出现次数


let s = 'atit patel';
let test5 = [...s].reduce((a, e) => { a[e] = a[e] ? a[e] + 1 : 1; return a }, {});
console.log(test5); //{a: 2,e: 1,i: 1,l: 1,p: 1,t: 3}

方法 2


let test6 = [...s].reduce((res, char) => (res[char] = (res[char] || 0) + 1, res), {})
console.log(test6);//{a: 2,e: 1,i: 1,l: 1,p: 1,t: 3}

# 重命名对象数组中的对象属性

使用 Map:此方法创建一个新数组,其中填充了对调用数组中每个元素调用提供的函数的结果


let countries = [
{ id: 1, name: "india" },
{ id: 2, name: "canada" },
{ id: 3, name: "america" }
];
const transformed = countries.map(({ id, name }) => ({
label: id,
value: name
}));
console.log("1", JSON.stringify(transformed));[{"label":1,"value":"india"},{"label":2,"value":"canada"},{"label":3,"value":"america"}]

使用带有参数的映射


const transformed2 = countries.map(({ id: label, name: value }) => ({
label,
value
}));
console.log("2", JSON.stringify(transformed2));
[{"label":1,"value":"india"},{"label":2,"value":"canada"},{"label":3,"value":"america"}]

使用对象解构


const rename = (({id: a_b_c, ...rest}) => ({a_b_c, ...rest}))
console.log(rename({id: 1, val: 2}))
//{a_b_c: 1, val: 2}

# 合并两个数组并创建一个新数组


var arr1 = ['a', 'b', 'c']
var arr2 = ['d', 'e']
var merged = [...arr1, ...arr2]
console.log(merged)

# 比较两个对象数组,删除重复项,根据属性合并对象


let array1 = [
{ id: "50", active: "a", value: 10 },
{ id: "51", active: "a", value: 11 }
];
let array2 = [
{ id: "53", active: "a", value: 10 },
{ id: "51", active: "a", value: 11 },
{ id: "52", active: "a", value: 13 }
];

创建函数


let res = array2.filter(val =>
    array1.some(({
        value
    }) => (val.value as any) === (value as any))
);
console.log("1", JSON.stringify(res));
//[{"id":"53","active":"a","value":10},{"id":"51","active":"a","value":11}]

# 比较两个对象数组,合并和更新值(假设数组 3,4 共享相同的 ID)


//拿上一条两个数组举例
let arr = [];
array1.map(id =>
    arr.push({
        id: id.id,
        newValue: array2.find(o => o.id === id.id).value + 2
    })
);
console.log("2", JSON.stringify(arr));
//[{"id":"50","newValue":12},{"id":"51","newValue":13}]

比较对象数组并找到唯一的对象


const ids = array1.map(e => e.id);
let filtered = array2.filter(e => ids.includes(e.id));
console.log("3", JSON.stringify(filtered));
//[{"id":"50","active":"a","value":12},{"id":"51","active":"a","value":15}]

# 根据匹配的值比较和更新属性


const array7 = [
{ id: "50", active: "a", value: 12 },
{ id: "51", active: "a", value: 15 }
];
const array8 = [{ id: "50", active: "a", value: 12 }];

const idSet = new Set(array8.map(o => o.id));
const res1 = array7.map(o => ({ ...o, value: idSet.has(o.id) ? "0" : o.value }));
console.log("4", JSON.stringify(res1));
//[{"id":"50","active":"a","value":"0"},{"id":"51","active":"a","value":15}

比较两个数组对象并获得差异


let a = [
{ id: "50", active: "a", value: 10 },
{ id: "51", active: "a", value: 11 }
];
let b = [
{ id: "50", active: "a", value: 10 },
{ id: "51", active: "a", value: 11 },
{ id: "52", active: "a", value: 13 }
];

let valuesArray1 = a.reduce(function(a, c) {
    a[c.value] = c.value;
    return a;
}, {});
let valuesArray2 = b.reduce(function(a, c) {
    a[c.value] = c.value;
    return a;
}, {});
var result = a
    .filter(function(c) {
        return !valuesArray2[c.value];
    })
    .concat(
        b.filter(function(c) {
            return !valuesArray1[c.value];
        })
    );
console.log("5", result);
//[{"id":"52","active":"a","value":13}]
//shorthand
let ab = b.filter(o => !a.find(o2 => o.id === o2.id));
console.log("6", ab);

# 比较对象的两个数组合并并删除重复项


const arr1IDs = new Set(a.map(({ id }) => id));
const combined = [...a, ...b.filter(({ id }) => !arr1IDs.has(id))];
console.log(JSON.stringify(combined));
//[{"id":"50","active":"a","value":10},{"id":"51","active":"a","value":11},{"id":"52","active":"a","value":13}]

比较对象并找到唯一值


let obj1 = {
val1: "test",
stream: { prop1: false, prop2: true }
};
let obj2 = {
val1: "test",
stream: { prop1: true, prop2: true }
};
interface Data {
stream: { [key: string]: boolean };
}
function objFilter(objA: Data, objB: Data): Data {
let out: Data = { stream: {} };
Object.keys(objA.stream).filter((value, idx) =>
Object.values(objA.stream)[idx] === Object.values(objB.stream)[idx]
? (out.stream[value] = Object.values(objA.stream)[idx])
: false
);
return out;
}
console.log(JSON.stringify(objFilter(obj1, obj2))); //prop2
//{"stream":{"prop2":true}}

# 处理循环内的多个服务调用

如果我们不想等待所有服务呼叫完成


let data = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }];
async function getDetails(values) {
    for (const data of values) {
        const result = await axios.get(
            `serviceURL/${data.id}`
        );
        const newData = result.data;
        this.updateDetails(newData);
        console.log(this.response);
    }
}
function updateDetails(data) {
    this.response.push(data);
}
getDetails(data); //call service to get data

等到所有服务呼叫完成


let data = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }];
async function getDetails(values) {
    const dataPromises = values.map(entry => {
        return axios.get(
            `serviceURL/${entry.id}`
        );
    });
const resultData = await Promise.all(dataPromises);
resultData.forEach((res: any) => {
        this.updateDetails(res.data);
    });
    console.log(this.response);
}
function updateDetails(data) {
    this.response.push(data);
}
getDetails(data); //call service to get data

# 数组的一部分复制到同一数组中的另一个位置 copyWithin()

copyWithin()方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组 。也就是说,使用这个方法,会修改当前数组。

它接受三个参数。

  • target(必需):从该位置开始替换数据。如果为负值,表示倒数。

  • start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。

  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。

这三个参数都应该是数值,如果不是,会自动转为数值。

;[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
1
2

上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。

下面是更多例子。

// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]

// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}

// 将2号位到数组结束,复制到0号位
let i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// 对于没有部署 TypedArray 的 copyWithin 方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# at()和 width()

使用负索引获取和更改元素值

const colors = ['pink', 'purple', 'red', 'yellow']
console.log(colors.at(1)) // purple

console.log(colors.with(1, 'blue'))
// ['pink','blue','red','yellow']

// Original not modified
console.log(colors)
// ['pink','purple','red','yellow']
1
2
3
4
5
6
7
8
9

# reduceRight() 从右到左计算数组求和

与 reduce()类似,但回调是从右到左而不是从左到右

const letters = ['b', 'e', 'a', 'u', 't', 'y']
const word = letters.reduce((word, letter) => word + letter, '')
console.log(word) // beauty
// Reducer iterations
// 1.('','y')=>''+'y'='y'
// 2.('y'+'t')=> 'y'+ 't'= 'yt’;
// 3.('yt','u')→'ytu';
// ...
// n.('ytuae','b')=> 'ytuaeb';
const wordReversed = letters.reduceRight((word, letter) => word + letter, '')
console.log(wordReversed) //ytuaeb
1
2
3
4
5
6
7
8
9
10
11

这是 reduceRight() 的另一个很好的场景

const thresholds =[
{ color:'blue',threshold:0.7 },
{ color:'orange',threshold:0.5}
{color:'red',threshold:0.2}];
const value = 0.9;
const threshold = thresholds.reduceRight(
    (color,threshold)=>
    threshold.threshold>value ?threshold.color :color
);
console.log(threshold.color);//red
1
2
3
4
5
6
7
8
9
10
11

# findLast() 最后一个元素开始查找数组项

非常适合从结束位置搜索比使用 find() 产生更好性能的情况

由于我们的目标对象更接近数组的尾部,findLast() 应该运行得更快

findLast() 的另一个用例是当我们必须从末尾专门搜索数组以获得正确的元素时。

例如,如果我们想查找数字列表中的最后一个偶数,find() 将产生完全错误的结果

知识汇总   |