撸js基础之数组
03月15日, 2017 JavaScript Tumars 7,404 views次
03月15日, 2017 7,404 views次
前言
前端这两年的新技术铺天盖地,各种框架、工具层出不穷眼花缭乱。最近打算好好复习下 js 基础,夯实的基础才是学习新技术的基石。本文作为读书笔记简单的总结下 js 数组的基础知识。
本系列另外还有一篇:撸js基础之对象,各位有兴趣的可以看下。
本文日后还会更新修改,如若转载请附上原文地址:http://www.ferecord.com/lujs-array.html,以便溯源。
数组基础
简介
数组是应用最广泛的数据存储结构。它被植入到大部分编程语言中。在 ECMAScript 中数组是非常常用的引用类型。
属性
length
length属性表示数组的长度,即其中元素的个数。
JavaScript数组的length属性是可变的,当length属性被设置得更大时,整个数组的状态事实上不会发生变化,仅仅是length属性变大;当length属性被设置得比原来小时,则原先数组中索引大于或等于length的元素的值全部被丢失。
prototype
返回对象类型原型的引用。prototype 属性是 object 共有的。
一般用来给数组实例添加方法。
constructor
表示创建对象的函数。
说明:constructor 属性是所有具有 prototype 的对象的成员。constructor 属性保存了对构造特定对象实例的函数的引用。
基本操作
创建数组
1 2 3 4 5 6 7 8 9 10 |
// 数组实例的创建 var arr = [] var arr = new Array() //创建一个空数组 [] var arr = new Array(5) //创建一个length为5的数组 [undefined, undefined, undefined, undefined, undefined] var arr = new Array(1,2,3,4,5) //创建数组并赋值 [1,2,3,4,5] var arr = Array.of(7); // 创建数组并赋值 [7] var arr = Array.of(1, 2, 3); // 创建数组并赋值 [1, 2, 3] |
检测数组
1 2 3 4 5 6 7 8 |
//判断一个对象是不是数组 var arr = [] if(arr instanceof Array){} // 方法一 if(Object.prototype.toString.call(arr) == '[object Array]')}{} // 方法二 if(Array.isArray(arr)){} //方法三 if(arr.constructor == Array){} // 方法四 |
数组方法 isArray, from, of
Array.isArray(obj)
检测对象是否 Array ,是则返回true,否则为false。
Array.from(arrayLike, mapFn, thisArg)
该方法从一个类似数组或可迭代对象创建一个新的数组实例。参数 arrayLike 是想要转换成真实数组的类数组对象或可遍历对象。mapFn 是可选参数,如果指定了该参数,则最后生成的数组会经过该函数的加工处理后再返回。thisArg是可选参数,为执行 mapFn 函数时 this 的值。
所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from方法转为数组。
实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的 arguments 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 } let arrayLike2 = {length: 3} let str = 'abcd' let newArray = Array.from(arrayLike) //['a', 'b', 'c'] let newArray2 = Array.from(arrayLike, (v) => v+'1') //['a1', 'b1', 'c1'] let newArray3 = Array.from(arrayLike2) // [undefined, undefined, undefined] let newArray4 = Array.from(str) // ['a', 'b', 'c', 'd'] |
Array.of(item…)
该方法用于创建数组实例。该方法用于替代 Array() 或 new Array()。Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个包含 7 个 undefined 元素的数组。
1 2 3 4 5 6 7 |
Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ] Array(1, 2, 3); // [1, 2, 3] |
数组实例方法
转换方法 join
arr.join(separator)
把数组构构造成字符串,它先把数组中的每个元素转换成字符串,然后再用 separator 分隔符把它们链接在一起,separator 分隔符默认是逗号 “,”,要想做到无间隔链接,可以使用空字符串作为 separator:
1 2 3 4 5 6 7 |
var arr = [1,2,3,4,5] arr.join('|') //"1|2|3|4|5" arr.join("") //12345 //另所有对象有具有的 toLocaleString、toString、valueOf,可以看作是join的特殊用法,不常用 |
栈方法 push, pop
arr.push(item…)
将一个或多个新元素添加到数组结尾,并返回数组新长度。
arr.pop()
移除最后一个元素并返回该元素值。
队列方法 unshift, shift
arr.unshift(item…)
将一个或多个新元素添加到数组开始,数组中的元素自动后移,返回数组新长度。
arr.shift()
移除最前一个元素并返回该元素值,数组中元素自动前移.如果这个数组是空的,它会返回 undefined。shift 通常比 pop 慢的多。
重排序方法 reverse, sort
arr.reverse()
反转数组的顺序。
arr.sort(comparefn)
给数组排序,默认升序。
注意 sort 默认会将数组内容视为字符串来排序,所以对数字排序时默认的排序规则会错的离谱。一般我们给sort带入个比较函数来替代原来的默认的比较方法,比较方法接受两个参数,如果两个参数相等则返回0,如果第一个参数应该排在前面则返回一个负数,如果第二个参数应该排在前面则返回一个正数:
1 2 3 4 5 6 7 |
//数组排序 var arr = [2,3,1,5,4] arr.sort(function(a, b) { return a - b }) // [1,2,3,4,5] |
操作方法 concat, slice, splice, copyWithin, fill
arr.concat(item…)
该方法产生一份 arr 的潜复制,并将多个数组(也可以是字符串,或者是数组和字符串的混合)附加在其后连接为一个数组,返回连接好的新的数组。
arr.slice(start, end)
该方法对数组中的一段做浅复制,首先复制数组 arr[start] 至 arr[end] 的部分,注意不包括 end 对应的元素,如果省略 end 将复制 start 之后的所有元素(或者理解成 end 的默认值为 arr.length)。字符串也有个同名方法 string.slice。
arr.splice(start, deleteCount, item…)
该方法从 arr 中移除一个或多个元素,并将新的 item 插入至移除元素的开始位置, 参数 start 是移除元素的开始位置,deleteCount 是要移除的元素的个数,item 是要被插入的元素。它返回一个包含被移除元素的数组。
arr.copyWithin(target, start, end)
该方法复制数组的一部分到同一数组中的另一个位置(会覆盖原成员),并返回修改后的数组。使用这个方法,会修改当前数组。参数 target 为开始替换数据的位置,若 target 大于等于 arr.length,将会不发生拷贝。start 是可选参数,为开始读取数据的位置,默认为0。end 是可选参数,为停止读取数据的位置,默认为 arr.length。
1 2 3 4 |
[1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5] |
上面代码表示将从3号位直到数组结束的成员(4和5),复制到从0号位开始的位置,结果覆盖了原来的1和2。
arr.fill(value, start, end)
该方法使用给定值填充一个数组,参数 value 是用来填充数组的值。start 是可选参数,为填充开始位置,默认为 0。end 是可选参数,为填充的结束位置,默认为 arr.length。
1 2 3 4 |
[1, 2, 3].fill(4) // [4, 4, 4] [1, 2, 3].fill(4, 1 , 2) // [1, 4, 3] |
fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
位置方法 indexOf, lastIndexOf, includes
arr.indexOf(searchElement, start)
该方法返回要查找的项在数组中的位置,如果没找到返回 -1。接受两个参数,searchElement 是要查找的项,start 是查找起始位置的索引,默认是0。
arr.lastIndexOf(searchElement, start)
从 start 位置开始向前查找,start 默认值为 arr.length - 1。
注意该方法在比较查找项与数组中每一项时,会使用全等操作符,也就是要求查找的项必须严格相等。
arr.includes(searchElement, fromIndex)
该方法用来判断当前数组是否包含某指定的值,如果是,则返回 true,否则返回 false。参数 searchElement 为需要查找的元素值。参数 fromIndex 是可选参数,从该索引处开始查找 searchElement,如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索,默认为 0。 如果fromIndex 大于等于数组长度 ,则返回 false 。该数组不会被搜索。
该方法属于ES7,但Babel转码器已经支持。
1 2 3 4 5 |
[1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, NaN].includes(NaN); // true |
没有该方法之前,我们通常使用数组的indexOf方法,检查是否包含某个值。
1 2 3 4 5 |
if (arr.indexOf(el) !== -1) { // ... } |
indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相当运算符(===)进行判断,这会导致对NaN的误判。includes使用的是不一样的判断算法,就没有这个问题。
1 2 3 4 5 6 |
[NaN].indexOf(NaN) // -1 [NaN].includes(NaN) // true |
includes() 方法有意设计为通用方法。它不要求this值是数组对象,所以它可以被用于其他类型的对象 (比如类数组对象)。
1 2 3 4 5 6 |
(function(){ console.log([].includes.call(arguments, 2)) // true console.log([].includes.call(arguments, 4)) // false })(1,2,3) |
迭代方法 every, some, filter, forEach, map, find, findIndex, entries, keys, values
arr.every(callback,thisArg)
对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。callback 被调用时传入三个参数:元素值,元素的索引,原数组。thisArg 为可选参数,指定执行 callback 时使用的 this 值。
arr.some(callback, thisArg)
对数组中的每一项运行给定函数,如果该函数对任意一项返回 true,则返回 true。
arr.filter(callback, thisArg)
对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
arr.forEach(callback)
对数组中的每一项运行给定函数,这个方法没有返回值。本质上与使用 for 循环迭代数组一样。
arr.map(callback)
对数组中的每一项运行给定函数,返回每次函数调用组成的数组。
arr.find(callback, thisArg)
该方法对数组所有成员依次执行 callback 函数,直到找出第一个返回值为 true 的成员,然后返回该成员。如果没有符合条件的成员,则返回 undefined。
1 2 3 4 |
[1, 4, -5, 10].find((v, i, arr) => v < 0) // -5 |
find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
arr.findIndex(callback, thisArg)
该方法与 arr.find() 类似,对数组中的成员依次执行 callback 函数,直至照吃第一个返回值为 true 的成员,然后返回该成员的索引。如果没有符合条件的成员,则返回 -1。
1 2 3 4 5 6 |
[1, 5, 10, 15].findIndex((v, i , arr)=>{ return v > 9 }) //2 |
arr.entries()
arr.keys()
arr.values()
这三个方法都返回一个新的Array Iterator对象,可以用for...of
循环进行遍历,区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem) ;} // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem);} // 0 "a" // 1 "b" var arr = ["a", "b"; var iterator = arr.entries(); // undefined console.log(iterator); // Array Iterator {} console.log(iterator.next().value); // [0, "a"] console.log(iterator.next().value); // [1, "b"] |
归并方法 reduce, reduceRight
arr.reduce(callback, initialValue)
arr.reduceRight(callback, initialValue)
这个两个方法都会迭代数组所有的项,然后返回一个最终值。reduce()方法从数组的第一项开始,逐个遍历到最后,而reduceRight()则从数组的最后一项开始,向前遍历到第一项。它们接受两个参数,callback 每一项上调用的函数,callback 被调用时传入四个参数:上一次调用回调返回的值、正在处理的元素、正在处理的元素的索引值(如果提供了 initialValue ,从0开始;否则从1开始)、原数组。initialValue 是可选项,作为归并基础的初始值,其值用于第一次调用 callback 的第一个参数。
数组常见问题练习
数组合并
多个一维数组合并
如有两个一维数组,要将他们合并成一个数组:
1 2 3 4 5 6 |
var arr1 = [1, 2] var arr2 = [3, 4] // => [1,2,3,4] |
Array.prototype.concat()方法
1 2 3 |
var arr = arr1.concat(arr2) //[1, 2, 3, 4] |
for循环和Array.prototype.push()
1 2 3 4 5 6 7 8 |
function flation(arr1, arr2) { for (var i = 0; i < arr2.length; i++) { arr1.push(arr2[i]) } return arr1 } |
reduce()或reduceRight()方法
1 2 3 4 5 6 7 8 9 |
function flatten(arr1, arr2) { return arr2.reduce(function (prev, curr) { prev.push(curr) return prev }, arr1) } |
多维(复合)数组合并成一维数组
例如有这么一组多维数组,要把它拍平成1维数组:
1 2 3 4 5 |
var myArray = [[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11]; // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
Array.prototype.push()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function flatten(arr, result) { if (!result) { result = [] } for (var i = 0; i < arr.length; i++) { if(arr[i].constructor == Array) { flatten(arr[i], r) } else { result.push(arr[i]) } } return result } flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11]) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
Array.prototype.concat()方法
1 2 3 4 5 6 7 8 9 10 11 12 |
//省略对二维以上数组的判断 function flatten(arr) { var result = [] for (var i = 0; i < arr.length; i++) { result = result.concat(arr[i]) } return result } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9]]);//[1, 2, 3, 4, 5, 6, 7, 8, 9] flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9],10,11]);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] |
可以通过Function.prototype.apply()方法,让其变得更简单:
1 2 3 4 5 6 |
//省略对二维以上数组的判断 function flatten(arr) { return Array.prototype.concat.apply([], arr) } |
还可以将上面方法做个精简:
1 2 3 4 5 6 |
//省略对二维以上数组的判断 function flatten(arr) { return [].concat.apply([], arr) } |
在 ES6 中,还可以这样写:
1 2 3 4 5 6 |
//省略对二维以上数组的判断 function flatten(arr) { return [].concat(...arr) } |
如果要处理三维或更多维数组,则需要加一些判断:
1 2 3 4 5 6 7 8 |
function flatten(arr) { arr = [].concat.apply([], arr) return arr.some(Array.isArray) ? flatten(arr) : arr } flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11]) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
或者:
function flatten(arr) {
var isArray = Object.prototype.toString.call(arr) == ‘[object Array]’;
1 2 3 4 5 6 7 8 9 |
if (isArray && arr.length > 0) { var head = arr[0] var tail = arr.slice(1) return flatten(head).concat(flatten(tail)); } else { return [].concat(arr) } |
}
使用join()和split()
利用数组实例的join()
方法和字符串实例的split()
方法,也可以将多维数组拍平:
1 2 3 4 5 6 7 |
function flatten(arr) { return arr.join(',').split(',') } flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11]) //["1", "2", "3", "4", "5", "6", "7", "8", "9", "11", "12", "12", "13", "14", "10", "11"] |
这种方法的缺点在于返回的数组内全是字符串,如果不需要校验内容类型的话,可以使用这种方法。
数组去重
双重循环去重
思路:
- 构建一个空数组来存放去重后的数组
- 对原数组做循环遍历,每次从数组中取出一个元素与结果数组做对比
- 如果原数组取出的元素与结果数组元素相同,则跳出循环;反之则将其存放到结果数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function unique(arr) { var result = [arr[0]] for (var i = 1; i < arr.length; i++) { var repeat = false for (var j = 0; j < result.length; j++) { if (arr[i] == result[j]) { repeat = true break; } } if (!repeat) { result.push(arr[i]) } } return result } unique([1, 2, 3, 4, 3, 2, 'a', 'b', 'a']); //[1, 2, 3, 4, "a", "b"] |
这种方法也可采用forEach()
方法和indexOf()
方法模拟实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function unique(arr) { var result = [arr[0]] arr.forEach(function(v) { if (result.indexOf(v) == -1) { //这里 indexOf()也可替换为es7的includes() result.push(v) } }) return result } unique([1, 2, 3, 4, 3, 2, 'a', 'b', 'a']); //[1, 2, 3, 4, "a", "b"] |
排序遍历去重
思路:
- 构建一个空数组来存放去重后的数组
- 用
sort()
方法对原数组做一个排序,排完序后对数组做遍历,检查数组中第 i 个元素与结果数组中最后一个元素是否相同,如果不同,则放到结果数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function unique(arr) { arr.sort(); var result = [] for (var i = 0; i < arr.length; i++) { if (arr[i] !== result[result.length - 1]) { result.push(arr[i]) } } return result } unique([1, 2, 3, 4, 3, 2, 'a', 'b', 'a']); |
这种方法有两个特色:
- 去重后的数组会做排序,主要是因为原数在去重前做了排序
- 去重后的数组,与数字相同的数字字符无法区分,比如‘1’和1
对象键值对法
思路:
- 创建一个 js 对象及新数组
- 遍历原数组,每次取出一个元素与 js 对象的键作对比
- 如果不包含,将存入对象的元素的值推入到结果数组中,并将 object 对象中该属性名的值设为1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function unique(arr) { var result = [] var object = {} for (var i = 0; i < arr.length; i++) { if (!object[typeof(arr[i]) + arr[i]]) { //键名里加入typeof(arr[i])是为了区别不同类型的值,如1和`1` result.push(arr[i]) object[typeof(arr[i]) + arr[i]] = 1 } } return result } unique([1, 2, 3, 4, 3, 2, '1', 'a', 'b', 'a']); //[1, 2, 3, 4, "a", "b"] |
这种方法比较耗内存,但运行下来耗时最少,是较为优秀的方案。
使用 ES6 的 Set 和 Map 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//借助 Map 数据结构 function unique(arr) { const seen = new Map() return arr.filter((v)=> !seen.has(v) && seen.set(v, 1)); } //借助 Set 数据结构 function unique(arr) { return Array.from(new Set(arr)) //或 return [...new Set(arr)] } unique([1, 2, 3, 4, 3, 2, '1', 'a', 'b', 'a']); //[1, 2, 3, 4, "1", "a", "b"] |
数组随机排序
递归的方法
思路:
不断从原数组中随机取一个元素放进新数组,同时删除原数组中该值,递归重复至全部取出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function randomSort(arr, newArr) { var newArr = newArr || [] if (arr.length == 1) { newArr.push(arr[0]) return newArr; // 相当于递归退出 } var random = Math.ceil(Math.random() * arr.length) - 1 newArr.push(arr[random]) arr.splice(random, 1) return randomSort(arr, newArr) } randomSort([1, 2, 3, 4, 5, 6, 7]); //[2, 3, 1, 5, 6, 7, 4] randomSort([1, 2, 3, 4, 5, 6, 7]); //[3, 4, 2, 5, 1, 6, 7] |
使用数组 sort 方法对数组元素随机排序(效果不佳)
思路:
使用srot()
每次比较时返回一个随机值,让数组内元素依次前后随机排序
1 2 3 4 5 6 7 8 9 10 11 |
Array.prototype.shuffle = function(n) { var len = this.length, num = n ? Math.min(n, len) : len, arr = this.slice(0) arr.sort(function(a, b){ return Math.random() - 0.5 }) return arr.slice(0, num) } [1, 2, 3, 4, 5, 6, 7].shuffle() //[1, 4, 2, 5, 6, 3, 7] |
这个方法虽然实现了随机排序,但由于sort()
方法是依次比较的,所以每个元素被随机到原位置后面的概率会越来越低。
随机交换数组内的元素 (原理from underscore.js)
思路:
遍历数组,每次从i位置后元素随机挑一个放到i位置,将原i位置元素放至被挑元素原位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Array.prototype.shuffle = function() { var len = this.length, arr = this.slice(0), temp, index; for (var i = 0; i < len; i++) { index = i + Math.floor(Math.random() * (len - i)) temp = arr[i] arr[i] = arr[index] arr[index] = temp } return arr.slice(0) } |
随机从原数组抽取一个元素,加入到新数组
思路:
遍历数组,每次从数组中随机挑一个元素(随机数最大值为原数组剩余长度),将该元素拿出来放入新数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Array.prototype.shuffle = function() { var len = this.length, arr = this.slice(0), result = [], index; for (var i = 0; i < len; i++) { index = Math.floor(Math.random() * (len - i)) console.log(index) result.push(arr.splice(index, 1)[0]) } return result } [1, 2, 3, 4, 5, 6, 7].shuffle() //[5, 3, 2, 1, 7, 4, 6] |
取数组中最大值最小值
遍历比较方法
思路:
- 设一个变量存放最大值,将数组中第一个值赋值给该变量
- 遍历数组与最大值变量比较,如果大于最大值,则将该值赋值最大值变量
- 遍历结束后,变量里储存的就是数组里的最大值
1 2 3 4 5 6 7 8 9 10 |
Array.prototype.max = function() { var max = this[0] this.forEach(function(v) { if (v > max) {max = v} }) return max } [1,45,23,3,6,2,7,234,56].max() // 234 |
归并比较方法
思路:
- 使用数组实例的 reduce(function(prev, curv, index, arr)) 方法
- 依次比较回调函数中参数 prev 与 curv 的大小,返回大的那个
1 2 3 4 5 6 7 8 |
Array.prototype.max = function() { return this.reduce(function(prev, curv) { return prev > curv ? prev : curv }) } [1,45,23,3,6,2,7,234,56].max() // 234 |
利用 Math.max() 与 Math.min() 方法
思路:
将数组转换成参数传进Math.max()
或Math.min()
。
1 2 3 4 5 6 |
Array.prototype.max = function() { return Math.max.apply({},this) //或 return Math.max(...this) } [1,45,23,3,6,2,7,234,56].max() // 234 |
将一个数按大小顺序插入数组并返回索引值
任务:
构建一个函数where(arr, num),函数接受两个参数,一个是数组arr,一个是要插进数组的数字num,函数将num按大小顺序插进arr,并返回num的索引值。例如:
1 2 3 4 5 |
where([1,2,3,4], 1.5) //1 where([20,3,5],19) //2 where([40,60],50) //1 |
使用 push + sort + indexOf 方法
思路:
- 通过
push()
或unshift()
方法将 num 插入 arr - 使用
sort()
对 arr 进行排序 - 使用
indexOf()
找出 num 在 arr 中的 index(或使用for、forEach、some循环) - 返回 index
1 2 3 4 5 6 7 8 9 10 11 12 |
function where(arr, num) { arr.push(num) arr.sort(function(a,b){ return a - b }) return arr.indexOf(num) } var a = [1,2,3,4] where(a, 1,5) //1, a = [1,1.5,2,3,4] |
或者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function where(arr, num) { arr.push(num) arr.sort(function(a,b){ return a - b }) var index; arr.some(function(v,i) { if(v === num) { index = i return true } }) return index } var a = [1,2,3,4] where(a, 1,5) //1, a = [1,1.5,2,3,4] |
使用 sort + findIndex + splice 方法
思路:
- 使用
sort()
对 arr 进行排序 - 使用 findIndex() 找出 arr 中第一个大于 num 的元素的位置
- 使用
splice()
将 num 插入该元素前
1 2 3 4 5 6 7 8 9 10 11 |
function where(arr, num) { arr.sort((a,b) => a-b) const index = arr.findIndex(v => v > num) arr.splice(index,0,num) return index } var a = [1,2,3,4] where(a, 1,5) //1, a = [1,1.5,2,3,4] |
从数组中寻找元素并删除元素
任务:
构建一个函数destroyer(arr, item…),传入数组与要删除的指定值,返回删除指定值后的数组,例如:
1 2 3 |
destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
arguments + indexOf + filter 遍历判断法
思路:
- 通过 arguements 对象分别获取到数组 arr 和指定要删除的元素,将指定元素转换成数组 removeArgs
- 使用
filter()
筛选出 arr 内与 removeArgs 内不相同的元素,筛选规则通过indexOf()
方法判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function destroyer(para) { var arr = arguments[0] var removeArgs = [] for(var i = 1; i < arguments.length; i++) { removeArgs.push(arguments[i]) } var isFalse = function(v) { return removeArgs.indexOf(v) === -1 } return arr.filter(isFalse) } destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
slice(或解构运算符) + es6 set + filter 方法
思路:
- 利用
call()
对 arguments 使用数组的slice()
分别获取到原数组和指定值 - 将指定值传进 new Set 对象
- 使用
filter()
筛选出 arr 内与 set 对象内不相同的元素,筛选规则通过 set 对象的has()
方法判断
1 2 3 4 5 6 7 |
function destroyer(para) { var removeArgs = new Set(Array.prototype.slice.call(arguments, 1)) return para.filter(v => !removeArgs.has(v)) } destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
也可以写成:
1 2 3 4 5 6 7 |
function destroyer(arr, ...items) { var removeArgs = new Set(items) return arr.filter(v => !removeArgs.has(v)) } destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
引用列表
本文内容主要参考摘录网站及数目为以下列表,感谢。
MDN 的 JavaScript 标准库 Array 部分
W3cplus 博客
《JavaScript高级程序设计(第3版)》
《JavaScript语言精髓(修订版)》
《ECMAScript 6 入门》
《高性能JavaScript(第1版)》
秀啊
真全!
哼,你怎么这么棒棒~~ 🙄 🙄 🙄
能把“省略对二维以上数组的判断”改成“只适用于最多二维数组”么
好的,谢谢提醒