数组常用的技巧总结
导读
前端开发中,数据处理是必不可少的一件事情,而且往往操作最多的数据类型-数组,下面来讲讲那些数据中都有哪些操作技巧。
01复制数组(深拷贝和浅拷贝)
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
先说浅拷贝:
//浅拷贝
let a = [1, 2, 3, 4];
let b = a;
console.log(a === b); // => true
b.push(5);
console.log(a); // => [1, 2, 3, 4, 5]
深拷贝:
02//深拷贝
let c = [1, 2, 3, 4];
let d = c.slice();
console.log(c === d); // => false
d.push(t);
console.log(c); // => [1, 2, 3, 4]
检查一个数组是否为对象
03//检查对象是否是数组
let numbers = [1, 2, 3, 4];
let strs = 'hello, world';
console.log(Array.isArray(numbers)); //=> true
console.log(Array.isArray(strs)); //=> false
//instanceof
console.log(numbers instanceof Array); //=> true
console.log(strs instanceof Array); //=> false
//构造方法检查
console.log(numbers.constructor == Array); //=> true
console.log(strs.constructor == Array); //=> true
删除数组中的指定一项
将项目添加到数组很容易,但是没有内置的等效项可以删除你添加的项目。您需要依靠indexOf和splice、delete关键字来创建自己的删除功能:
//删除一个指定元素
let eventNumbers = [1, 2, 3, 4, 5, 6, 7, 8];
//splice实现
eventNumbers.splice(eventNumbers.indexOf(7), 1);
console.log(eventNumbers); // => [1, 2, 3, 4, 5, 6, 8]
//delete实现
let eventNumbers2 = [1, 2, 3, 4, 5, 6, 7, 8];
delete eventNumbers2[eventNumbers2.indexOf(7)];
console.log(eventNumbers2); // => [1, 2, 3, 4, 5, 6, empty, 8]
console.log(eventNumbers2.length); // => 8
使用delete关键字发生的唯一事情是,已删除项设置为空值,但数组长度是不变的。
04清空数组
要清空并删除数组中的所有内容,最简单的方法(也是最快的方法!)简单粗暴,将数组的length属性设置为0:
05//清空一个数组
let ary1 = ['苹果', '香蕉', '橘子'];
ary1.length = 0;
console.log(ary1); // => []
console.log(ary1.length); // => 0
数组去重
之前讲过一篇很全面的,感兴趣的朋友可以往前面找找,也可以在公众号中的菜单中JS方法那里快速浏览。
使用ES6和Set对象,从数组中删除重复的值非常简单:
06//数组去重
let names = ["张三", "李四", "王五", "王五", "六六"];
let uniqueNames = [...new Set(names)];
console.log(uniqueNames); // => ["张三", "李四", "王五", "六六"]
数组排序
JavaScript中的数组带有一个方便的内置排序方法(sort),该方法使你可以精确指定排序方式。看下面的示例,在该示例中我们对一些数字和字符串进行排序:
//数组排序
let numbers2 = [3, 10, 2, 14, 7, 2, 9, 5];
let beatles = ["Ringo", "George", "Paul", "John"];
numbers2.sort(compareValues);
beatles.sort(compareValues);
function compareValues(a, b) {
if (a < b) {
// 如果a小于b
return -1;
} else if (a > b) {
// 如果a大于b
return 1;
} else {
// a = b
return 0;
}
}
console.log(numbers2); // => [2, 2, 3, 5, 7, 9, 10, 14]
console.log(beatles); // => ["George", "John", "Paul", "Ringo"]
compareValues方法的开放性很大,大家可以根据自己的需求来编写。
07随机排序
如果要随机重新排列数组的所有内容,在数组的原型上添加方法:
//随机排序
Array.prototype.shuffle = function () {
let input = this;
for (let i = input.length - 1; i >= 0; i--) {
let randomIndex = Math.floor(Math.random() * (i + 1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
return input;
}
let tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(tempArray.shuffle()); // => [6, 7, 3, 1, 4, 8, 9, 2, 5]
console.log(tempArray.shuffle()); // => [6, 7, 3, 1, 4, 8, 9, 2, 5]
这个方法以后用在颜色渲染列表中应该是个不错的选择。
08随机抽取一个元素
如果需要从我们的数组中随机选择一个元素,我们可以结合“随机数”的一些概念,并将其应用于以数组为中心的世界。该代码段将是:
//随机抽取一个元素
let myArray = ["书籍", "手机", "电脑", "平板"];
console.log(myArray[Math.floor(Math.random() * myArray.length)]); // => 电脑
console.log(myArray[Math.floor(Math.random() * myArray.length)]); // => 平板
console.log(myArray[Math.floor(Math.random() * myArray.length)]); // => 手机
哈哈哈,这玩意用在抽奖上可是妥妥的,不过这是会重复的。
09合并数组
这个我记得前面单独拿了一个章节来讲这个,里面有很多种很全面的方法,有兴趣的朋友可以去翻一翻。
10//数组合并
let smileys = ["😀", "😇", "😛", "🥶"];
let foods = ["🍊", "🥦", "🍔", "🍕", "🍰"];
let animals = ["🐙", "🐝", "🐈"];
let combined = [...smileys, ...foods, ...animals];
console.log(combined); // => ["😀", "😇", "😛", "🥶", "🍊", "🥦", "🍔", "🍕", "🍰", "🐙", "🐝", "🐈"]
元素交换
参考的是冒泡排序的方法,用来做两个元素交换。
11//元素交换
let myData = ["a", "b", "c", "d", "e", "f", "g"];
let temp = myData[2];
myData[2] = myData[5];
myData[5] = temp;
console.log(myData); // => ["a", "b", "f", "d", "e", "c", "g"]
数组转json
原始数组项的索引位置将为键,而相应数组项的内容将为值。
12//数组转json
let airportCodes = ["SFO", "LAX", "SEA", "NYC", "ORD", "ATL"];
let airportCodesObject = { ...airportCodes };
console.log(airportCodesObject); // => {0: "SFO", 1: "LAX", 2: "SEA", 3: "NYC", 4: "ORD", 5: "ATL"}
反转数组
利用数组的reverse来实现:
//reverse 反转数组
let numbers3 = [1, 2, 3, 4, 5, 6];
numbers.reverse();
console.log(numbers); // => [4, 3, 2, 1]
这个操作是在原来的数组上进行的,如果我们想数组进行反转之后,输出到一个新数组,可以这样来:
//返回一个新数组
let numbers4 = [1, 2, 3, 4, 5, 6];
let reversed = [...numbers4].reverse();
console.log(numbers4); // => [1, 2, 3, 4, 5, 6]
console.log(reversed); // => [6, 5, 4, 3, 2, 1]
由此可见,原数组并不受影响。
13检查所有元素满足某种条件
来做个测试,利用数组的every方法来检查数组中的元素是否都满足偶数:
//判断满足偶数条件
let someNumbers = [2, 4, 38, 20, 10, 13, 42];
function isEven(currentItem) {
if (currentItem % 2 === 0) {
return true;
}
}
console.log(someNumbers.every(isEven)); // => false
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供);
14检查某些元素满足某种条件
上面一点讲了要所有元素满足条件才为真,那么这里用some 方法来检查只有某个元素达到条件,就为真:
//部分条件满足
let highScores = [46, 191, 38, 10, 156];
function isReallyHighScore(currentItem) {
if (currentItem > 100) {
return true;
}
}
console.log(highScores.some(isReallyHighScore)); // => true
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
15数组降维
对宇宙观有了解的朋友应该都知道什么是降维打击,很经典的降维打击,出自中国科幻作家刘慈欣的经典作品《三体》一书,是指外星人使用“二向箔”将太阳系由三维空间降至二维空间的一种攻击方式。
那么在数组中,有一维数组、二维数组,三维数组...甚至到n纬数组,如果要把三维数组、二维数组转为一维数组,可以这么操作:
//数组降维
let cool = [1, 2, [1, 2, [1, 2]]];
//
console.log(cool.flat(1)); // => [1, 2, 1, 2, [1, 2]]
//
console.log(cool.flat(2)); // => [1, 2, 1, 2, 1, 2]
在此示例中,我们的cool数组具有两个嵌套数组级别。通过将深度值指定为1,我们告诉 flat 方法将数组平整一层,仅保留一层嵌套数组,指定为2,将数组中2层嵌套都降为一维数组。
有时你想完全降为一维数组,因此你可以为深度指定一个较大的数值。如果你不知道数组嵌套的深度,则可以舍弃该深度的最终值以展平任何深度的任何数组:
//n纬打击
let cool2 = [1, 2, [[[[[1]]]], 2, [1, 2]]];
let flatCool = cool2.flat(Infinity);
console.log(flatCool); // => [1, 2, 1, 2, 1, 2]
你可以为flat方法指定Infinity的深度值,这将确保数组在所有情况下都是一维数组显示的。
最后
其实编程也就是万变不离其宗,上面讲的这些或许不一定每样都用得上,但是,当你见过,有印象,为你以后在编程提供了思路也是很不错的。
世界不会在意你的自尊,人们看到的只是你的成就。在你没有成就以前,切勿过分强调自尊。
--《了不起的盖茨比》