本文总结了数组常用的迭代方法,还有修改数组的方法,以及在vue中,如何修改数组可以使得页面同样也能改变,对这些方法进行了总结。
1、js中关于操作数组的方法
迭代方法 | 接受的参数 | 返回值类型 | 作用 | 使用场景 |
---|---|---|---|---|
some() | – | true,false | 只要有一个元素满足就返回true | |
every() | – | true,false | 必须每一个元素都满足,才返回true | |
forEach() | – | 如果没有return,则不返回任何数据 | 不返回任何数据,可以操作数组里面的元素。 | |
map() | – | 返回一个新的数组 | 中有return,可以返回一个新数组 | |
filter() | 当前元素的值,当前值的索引索引 | 返回一个新的数组 | 返回一个filter中最后的return为true的数组 | 常用于过滤数组中的重复项 |
find() | 当前元素的值,当前值的索引索引 | 单个数值/undefined | 返回第一个满足条件的元素,没有就是undefined | |
findIndex() | 当前元素的值,当前值的索引索引 | return true : 循环结束。 找到了,此时返回值就是下标。return false : 循环继续。 没找到,循环继续。 如果所有元素全部遍历还是没找到,最终结果就是-1 | 返回满足条件的第一个元素的索引 | |
reduce() | 上一次回调函数的返回值、当前元素值、当前索引、当前数组 | 当前数组归并后的结果 。可以单个返回值,也可以是一个新的数组 | 可以将前面数组想遍历产生的结果与当前遍历项进行运算 | 求和 |
2、改变原数组的方法:
这些方法,vue都进行了重写 ,因此通过这些方法去修改数组的话,前台页面同样也会进行更新。
- push()、pop():模拟了栈的方法,先进先出,push(进),pop(出)
- shift()、unshift():模拟了队列的方法,先进后出
- splice():可以对特定索引值的数进行修改或者删除
- sort():排序
- reverse():对数组进行反转
3、别的方法
- Array.from():用于将两类可以把对象转换为真正的数组:类似数组的对象和可遍历的对象。
- slice():从原数组中返回选定元素的数组(这种方法不会改变原始数组)
2、代码说明
1、js中数组遍历的十种方法
- some() 只要有一个元素能满足条件就返回true,否则返回false,退出循环。
const arr = ['red', 'green', 'blue'];
arr.some((elem, index) => {
if (index >= 2) {
return true; // 中止循环
}
console.log(elem);
});
// Output:
// 'red'
// 'green'
- every() 每一个元素必须满足条件,就返回true,否则返回false
var numbers=[1,2,3,4,5,4,3,2,1];
var everyResult = number.every(function(item,index,array){
return(item>2);
});
console.log(everyResult)); //false
- forEach()
someArray.forEach((elem, index) => {
console.log(elem, index);
});
//如果想要返回一个新的数组,需要return
var list = [1, 2, 3, 4, 5];
var list2=list.forEach((item) => {
return item = item * 2;
})
console.log(list2)//2,4,6,8,10
- map()
返回的是一个新数组,数组中的元素为原始数组元素调用函数处理后的值。map不加return就跟forEach是一样的。
var numbers = [1,2,3,4,5,4];
var mapResult = numbers.map(function(item,index,array){
return item*2;
});
console.log(mapResult); //[2,4,6,8,10,8]
//数组里面每一项都会被处理。如果没有return,就会变成undefined
var array1 = [1, 4, 9, 16];
const map1 = array1.map(x => {
if (x == 4) {
return x * 2;
}
});
// map1 :[undefined, 8, undefined, undefined]
- filter()
对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
var numbers = [1,2,3,4,5,3,3,2,1];
var filterResult = numbers.filter(function(item,index,array){
return(item>2);
});
console.log(filterResult); //[3,4,5]
- find()
遍历数组,返回符合条件的第一个元素,如果没有符合条件的元素则返回undefined,不会改变原数组。
//查找大于100的元素
let arr = [10,20,30,40,50];
var result= arr.find(function(item,index,arr){
return item>20;
}
console.log(result)//30
var result= arr.find(function(item,index,arr){
return item>100;
}
console.log(result)//undefined
- findIndex()
遍历数组,返回符合条件的第一个元素的索引,如果没有就返回-1。
适合场景:适用于数组中元素为对象类型,比传统额for循环更高效
let arr = [
{ name: '张三', age: 20 },
{ name: '李四', age: 30 },
{ name: '王五', age: 25 },
{ name: '赵六', age: 33 },
{ name: '小七', age: 10 },
];
let i=arr.findIndex((item,index)=>{
return item.age>30
})
//打印的i为符合条件的第一个元素下标
console.log(i)//3
- for …of…(es6)
const arr = ['a', 'b', 'c'];
arr.prop = 'property value';
for (const elem of arr) {
console.log(elem);
}
// Output:
// 'a'
// 'b'
// 'c'
- for…in…
用于遍历数组或者对象的属性 ,遍历数组的时候,只会遍历出索引,遍历对象的时候会遍历他的属性key
const arr = ['a', 'b', 'c'];
for (item in arr) {
console.log(item );
}
// Output:
// 0
// 1
// 2
//正确写法
const arr = ['a', 'b', 'c'];
for (item in arr) {
console.log(arr[item]);
}
// Output:
// a
// b
// c
注意:最好不要用for...in...去迭代一个数组。for...in...不会按照属性的下标输出。
在循环便利时,会先把当中的非负整数键提出来,排序好输出,然后将剩下的定义时的顺序输出。所以再定义对象的时候,最好不要用纯数字定义键名。
var obj = {'-2':'-2-2','1':'11','6':'66','4':'44','-1':'-1-1'};
for (var i in obj ){
console.log(obj[i]);
}
- for
const arr = ['a', 'b', 'c'];
for (let index=0; index < arr.length; index++) {
console.log(index, arr[index]);
}
// Output:
// 0, 'a'
// 1, 'b'
// 2, 'c'
- reduce(),是数组的归并方法,与 forEach()、map()、filter()等迭代方法一样都会对数组每一项进行遍历,但是reduce() 可同时将前面数组项遍历产生的结果与当前遍历项进行运算,这一点是其他迭代方法无法企及的。
接受四个参数:
- 初始值(或者上一次回调函数的返回值)
- 当前元素值
- 当前索引
- 调用 reduce 的数组
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
求和运算:
const arr = [1,2,3,4,5];
const sum = arr.reduce(function(prev,cur,index,arr){
console.log(prev,cur,index);
return prev + cur;
});
console.log(sum);//15
最常见的就是for循环了。当我们不想从第一个数组元素开始遍历的话,就可以用他。
2、改变原数组的方法
如果我想要在更新数组中的某个值之后,在页面上同步更新的话,采用以下方法是行不通的:
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
<button @click="updateList" style="height: 20px; width: 50px"></button>
updateList(){
this.list[0]=8;
console.log(this.list);
}
点击按钮之后,list数据是改变了,但是页面上的数据还没有改变,
如何解决这个问题,有以下几个方法:
//方法一:采用Vue.set
this.$set(this.list, 1, 6);
//方法二:采用splice方法
this.list.splice(0, 1, 7);
//方法三:this.$forceUpdate()强制刷新
this.list[0]=8;
this.$forceUpdate()//强制刷新
//方法四:扩展运算符
this.list[0]=8;
this.list=[...this.list];
还有另外的几种修改数组的方法:
var list = [1, 3, 9, 4, 5];
// 删除最后一个数5
list.pop();// [1, 3, 9, 4]
// 数组中最后一个值后面加入100
list.push(100);//[1, 3, 9, 4, 5, 100]
// 删除数组第一个数
list.shift();// [3, 9, 4, 5]
// 往数组的开头处添加200
list.unshift(200);//[[200, 1, 3, 9, 4, 5]]
// 排序
list.sort();// [1, 3, 4, 5, 9]
// 删除下标为1,长度为2的值
list.splice(1, 1);
console.log(list);// [1, 9, 4, 5]
// 修改下标为1, 的值为100
list.splice(1, 1, 100);
console.log(list);// [1, 100, 9, 4, 5]
3、其他方法
Array.from()方法
Array.from()方法就是将一个类数组对象或者部署了Iterator接口的对象(Set、Map、Array)转换成一个真正的数组。
注意:一定要有length属性
length属性的长度是除了本属性其他属性的个数
类数组的key是数字
下标必须从0开始
这个是下标没有从0开始的
var list = {
1: "哈哈",
2: "我",
3: [1, 2, 3, 4],
4: { age: 12, name: 'haha' },
length: 5
};
const arr = Array.from(list);
console.log(arr)
这个是索引是字符的,同样也报错。
var list = {
0: "哈哈",
aa: "我",
2: [1, 2, 3, 4],
3: { age: 12, name: 'haha' },
length: 4
};
const arr = Array.from(list);
console.log(arr)
4、Array.from()的应用场景
- 将字符串转成数组
- 数组去重
- arguments转对象
- set转数组
//将字符串转成数组
var s = "hahah"
var arr = Array.from(s);
console.log(arr)// ['h', 'a', 'h', 'a', 'h']
//数组去重
var s = "hahah"
var arr = Array.from(new Set(s));
console.log(arr)//['h', 'a']
//arguments转对象
// 求最大值
function max() {
return Math.max.apply(null,Array.from(arguments))
}
console.log(max(16,28,23)) // 28
slice()
从原数组中返回选定元素的数组(这种方法不会改变原始数组)
array.slice(start,end)
参数
- start: 必需。整数,规定从何处开始选取,使用负数可从数组结尾处规定位置
- end: 可选。规定从何处结束选取。如果未指定参数,则从start开始一直截取到数组结尾
var bill = [5, 5, 10, 16, 20];
console.log(bill.slice(2));//10,16,20
console.log(bill.slice(2, 3));//10
splice、slice区别
1:splice会修改原数组,slice不会
2:splice可以删除、修改、替换原数组,slice只能截取数组中的值并生成新数组
3:splice可传递多个参数,slice最多只能传递两个参数
3、贪心算法一点小心得
贪心算法的最重要的思想是局部最优以达到全局最优,因此在想思路的时候可以先从局部入手,多想这步计算得到的结果,跟上步的结果哪个更优。
例如:求最大子树组和,leetcode(53题)