javascript中数组的常用算法深入分析

前言

Array是Javascript构成的一个重要的部分,它可以用来存储字符串、对象、函数、Number,它是非常强大的。因此深入了解Array是前端必修的功课。本文将给大家详细介绍了javascript中数组的常用算法,下面话不多说了,来一起看看详细的介绍吧

一、不改变原数组,返回新数组(字符串)

1、concat()   连接两个或者多个数组,两边的原始数组都不会变化,返回的是被连接数组的一个副本。

2、join()  把数组中所有的元素放入到一个字符串中,返回字符串

var a = [1,2,3];
a.join([4,5,6]); // "14,5,624,5,63"
a.join('sau');  // "1sau2sau3"

3、slice()    从开始到结束(不包括结束)选择数组的一部分浅拷贝到一个新数组

var a = [1,2,3,4,5];
a.slice(0,0);  //[]
a.slice(0,1);  //[1]
a.slice(2,4); //[3,4]
a.slice(0,5); //[1,2,3,4,5]
a.slice(10,1); //[]
a.slice(4); //[5]

4、map()   创建一个新的数组并返回,其中新数组的每一个元素由调用原始数组中的每一个元素执行提供的函数得来,原数组不变

5、every()  对数组中的每一个元素都执行一次指定的回调函数,直到回调函数返回false,此时every()返回false并不再继续执行,如果回调函数都对每一个元素都返回true,那么every()返回true。

6、some()  对数组中的每一个元素都执行一次指定的回调函数,直到回调函数返回true,此时some()返回true并不再执行。如果回调函数对每一个元素都返回false,那么some()将返回false。

7、filter()   创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

二、改变原数组

1、forEach()   针对每一个元素执行提供的函数。会修改原来的数组,不会返回执行结果,返回undefined。

2、pop()   删除数组最后一个元素,返回被删除的元素的值,如果数组为空,则不改变数组,返回undefined。

3、push()   向数组末尾添加一个或多个元素,返回改变后数组的长度。

4、reverse()   颠倒数组中元素的位置,返回该数组的引用。

5、shift()   从数组中删除第一个元素,改变原数组,并返回该元素的值。

6、unshift()   将一个或者多个元素添加到数组的开头,并返回新数组的长度。

7、sort()   对数组的元素进行排序,返回数组。排序不一定是稳定的。默认排序顺序是根据字符串unicode码点。

8、splice()   向数组中添加/删除元素,然后返回被删除的新数组()。

var a = [1,2,3,4,5];
a.splice(0,1);  //删除从0位置开始的1个 返回[1] a为[2,3,4,5]
a.splice(1,0,99) //在1的位置插入99 [2,99,3,4,5]
a.splice(1,1,88) //99替换为88 [2,88,3,4,5]

三、遍历方法

1、获取属性名:for...in  和object.key()的区别

答:1、for in 遍历对象可以枚举的属性名列表,包括[[prototype]]原型链;

2、Object.keys() 只查找属性名是否在对象中,返回一个数组,包含所有可以枚举的属性名;

3、Object.getOwnPropertyNames()只查找属性名是否在对象中,返回一个数组,包含所有的属性名,不论是否可枚举。

2、获取属性值: for... of 和object.values()

for of 语句:遍历可迭代对象的可枚举属性值列表,包括[[propertype]]原型链;

object.values() :返回一个给定对象自身的所有可枚举属性的值,不包括原型链。

四、ES6语法Map键值对转化为数组

new Map创建一个map

// new Map创建一个map
let map = new Map([[1,"one"], [2,"two"], [3,"three"]]);
map.set(4, "four");

// 获取所有键值对
console.log("获取key")
console.log([...map.keys()]) // 输出[1, 2, 3, 4]

console.log("获取value")
console.log([...map.values()]) // 输出[one, two, three, four]

console.log("获取map数组")
console.log([...map]) // 输出[[1, "one"], [2, "two"], [3, "three"], [4, "four"]]

五、两个升序的数组合并成一个升序数组

1、时间复杂度O(M+N),空间复杂度O(M+N)

function merge(left, right){
 let result = [],
  il  = 0,
  ir  = 0;

 while (il < left.length && ir < right.length) {
  result.push(left[il] < right[ir] ? left[il++] : right[ir++]);
console.log(result);
 }

 return result.concat(left.slice(il)).concat(right.slice(ir));
}

2、时间复杂度O(M+N),空间复杂度O(1)

 // m, n 是数组长度
function merge(left, m, right, n) {
 var i = m - 1, j = n - 1, writeIdx = m + n - 1;
 while (i >= 0 && j >= 0)
 left[writeIdx--] = left[i] > right[j]? left[i--] : right[j--];
 while (j >= 0)
 left[writeIdx--] = right[j--];
 return left;
}

六、数组重复问题

(一)数组去重

1、reduce方法

const distinct = arr => arr.sort().reduce( (init, current) => {

 if (init.length === 0 || init[init.length - 1] !== current) {
  init.push( current );
 }
 return init;
}, []);

let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
distinct(arr); // [1, 2, 3, 4, 5]

2、filter方法

const distinct = arr => arr.filter( (element, index, self) => {
 return self.indexOf( element ) === index;
});

let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
distinct(arr); // [1, 2, 3, 5, 4]

(二)排序数组去重

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {

 if(!nums || nums.length == 0) return 0;

 let len = 0;
 for(let i = 1; i < nums.length; i++) {
  if (nums[len] != nums[i]) {
   nums[++ len] = nums[i];
  }
 }
 return len + 1;
};

(三)判断数组是否存在重复

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var containsDuplicate = function(nums) {

 let hashMap = new Map();
 for(let i = 0; i < nums.length; i++) {

  if( hashMap.has(nums[i]) ) {
   return true;
  }

  hashMap.set(nums[i], 1);
 }

 return false;
};

七、两个数组的交集

给定两个数组,写一个方法来计算它们的交集。

例如:

给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].

注意:1、出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。2、

我们可以不考虑输出结果的顺序。

跟进:1、如果给定的数组已经排好序呢?你将如何优化你的算法?2、如果 nums1 的大小比 nums2 小很多,哪种方法更优?3、如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?

解法:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {

 var map1 = new Map();
 var number = [];

 for(var i = 0; i < nums1.length; i++) {
  var map1Value = map1.get(nums1[i]);
  map1.set( nums1[i], ( map1Value ? map1Value : 0 ) + 1 );
 }

 for(var i = 0; i < nums2.length; i++) {
  if( map1.has(nums2[i]) && map1.get(nums2[i]) != 0 ) {
   number.push(nums2[i]);
   map1.set( nums2[i], map1.get(nums2[i]) - 1 );
  }
 }

 return number;
};

八、找出一个数组中只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {

 let number = 0;
 for(let i = 0; i < nums.length; i++) {
  number ^= nums[i];
 }
 return number;
};

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Javascript之高级数组API的使用实例

    JS中我们可以根据需求新建新的对象解决问题的同时,也有一些常用的内置对象供我们使用,我们称之为API,本篇文章只是对数组部分进行了练习. 例一:伪数组,不能修改长短的数组(所以没办法清零),可以修改元素,代码实现如下: <script> fn(1,2); fn(1,2,3,4,5,6); fn(1,2,4,5,7,9,4); function fn(a,b){ arguments[0]=0; console.log(arguments); arguments.push(1); console.

  • JavaScript中常用的简洁高级技巧总结

    前言 编程是一件很快乐的事,实现一个目的,我们可以有很多方法路径,在这篇文章我们介绍一些JavaScript的奇技淫巧,仅供大家参考,各路大神在平时的代码编写时,如很多简洁高效的书写方式: 下面话不多说了,来一起看看详细的介绍吧 一.数据类型检测 1.1 typeof typeof操作符返回一个字符串,表示未经计算的操作数的类型:该运算符数据类型(返回字符串,对应列表如图) 1.2 instanceof var str = "This is a simple string"; var

  • JavaScript解析机制与闭包原理实例详解

    本文实例讲述了JavaScript解析机制与闭包原理.分享给大家供大家参考,具体如下: js解析机制: js代码解析之前会创建一个如下的词法环境对象(仓库):LexicalEnvironment{ } 在扫描js代码时会把: 1.用声明的方式创建的函数的名字; 2.用var定义的变量的名字存到这个词法环境中; 3.同名的时候:函数声明会覆盖变量,下面的函数声明会覆盖上面的同名函数; 4.函数的值为:对函数的一个引用; 变量的值为undefined; 5.如果用函数表达式的方式创建一个函数: va

  • 详解JavaScript函数callee、call、apply的区别

    arguments.callee 关于callee的解释:callee 是 arguments 对象的一个属性.可以用于引用该函数的函数体内当前正在执行的函数.这在函数的名称是未知时很有用,例如在没有名称的函数表达式 (也称为"匿名函数")内. 递归调用实现一个阶乘函数: function sum(num){ if(num <= 1){ return 1; }else{ console.log(num, arguments.callee(num-1)); return num *

  • JavaScript实现预览本地上传图片功能完整示例

    本文实例讲述了JavaScript实现预览本地上传图片功能.分享给大家供大家参考,具体如下: <html> <head> <title>www.jb51.net 图片上传预览</title> <script> function PreviewImage(imgFile) { var pattern = /(\.*.jpg$)|(\.*.png$)|(\.*.jpeg$)|(\.*.gif$)|(\.*.bmp$)/; if (!pattern.t

  • 详解javascript 变量提升(Hoisting)

    简介 "变量提升"意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确. 实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中. 声明变量的方法 var.let.const 不用以上关键字直接赋值的变量会挂载与windows环境下; let a=9 const a=1 var a=6 c=5 声明函数的方法 javascript中声明函数的方法有两种:函数声明式和函数表达式. //函数声明 function say(){ console.log('

  • JavaScript使用小插件实现倒计时的方法讲解

    CountDown.js 一个用来实现简单页面倒计时的轻量级工具 API CountDown.openTimeCountBySeconds()根据要计时的秒数打开一个显示剩余时间的倒计时 参数: Ele: 放置倒计时的元素 CountDownSeconds: 要计时的秒数 Sign: 用于给倒计时设置标记 (可以给多个倒计时设置同一个标记) Divider: 分割时分秒的分割符 EndFunc: 倒计时结束时执行的方法 ps:以上均为可选参数 示例 CountDown.openTimeCount

  • JavaScript碎片—函数闭包(模拟面向对象)

    经过这几天的博客浏览,让我见识大涨,其中有一篇让我感触犹深,JavaScript语言本身是没有面向对象的,但是那些大神们却深深的模拟出来了面向对象,让我震撼不已.本篇博客就是在此基础上加上自己的认知,如有错误,还请见谅. 具体来说实现模拟面向对象主要是利用JavaScript函数闭包这个概念.由于JavaScript中的每一个function都会形成一个作用域,而如果变量声明在这个域中,那么外部是无法直接去访问,要想访问必须new出一个实例来,相当于Java中class.首先让我们来了解一下pr

  • Javascript读写cookie的实例源码

    今天把javascript如何用来创建及存储cookie复习了一下,其中的一点体会拿出来和大家讨论,首先看一下基础知识: 什么是cookie cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 cookie 的值. cookie的例子 名字 cookie: 当访问者首次访问页面时,他或她也许会填写他/她们的名字.名字会存储于 cookie 中.当访问者再次访问网站时,他们会收到类似 "

  • JavaScript函数的4种调用方法实例分析

    本文实例讲述了JavaScript函数的4种调用方法.分享给大家供大家参考,具体如下: JavaScript 函数有 4 种调用方式: 1. 作为一个函数调用 2. 函数作为方法调用 3. 使用构造函数调用函数 4. 作为函数方法调用函数 分述如下: 每种方式的不同方式在于 this 的初始化. 作为一个函数调用 function myFunction(a, b) { return a * b; } myFunction(10, 2); // myFunction(10, 2) 返回 20 以上

随机推荐