数组常用的技巧总结
导读
前端开发中,数据处理是必不可少的一件事情,而且往往操作最多的数据类型-数组,下面来讲讲那些数据中都有哪些操作技巧。
01复制数组(深拷贝和浅拷贝)
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
先说浅拷贝:
//浅拷贝let a = [1, 2, 3, 4];let b = a;console.log(a === b); // => trueb.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); // => falsed.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)); //=> trueconsole.log(Array.isArray(strs)); //=> false//instanceofconsole.log(numbers instanceof Array); //=> trueconsole.log(strs instanceof Array); //=> false//构造方法检查console.log(numbers.constructor == Array); //=> trueconsole.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小于breturn -1;} else if (a > b) {// 如果a大于breturn 1;} else {// a = breturn 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//数组转jsonlet 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的深度值,这将确保数组在所有情况下都是一维数组显示的。
最后
其实编程也就是万变不离其宗,上面讲的这些或许不一定每样都用得上,但是,当你见过,有印象,为你以后在编程提供了思路也是很不错的。
世界不会在意你的自尊,人们看到的只是你的成就。在你没有成就以前,切勿过分强调自尊。
--《了不起的盖茨比》
