JavaScript数据结构与算法——数组

js数据结构与算法——数组

(一)小编有话说

这段时间没有更新文章先给读者们道个歉,因为个人心态等原因没有把自己所学的写博客,这段时间自学了vue全家桶还有node.js,后续我会重新的去整理出它们的学习笔记

(二)重要性

数据结构和算法对于不管是什么方向的程序员来讲都是非常重要的,不仅仅是为了过面试,还有我们不可能在整个职业生涯中仅仅做一个crud boy,所以我想开拓一个新的模块和大家一起学习js版数据结构与算法。

(三)我们为什么用数组

举个例子:

现在有这样一个需求:保存所在城市每个月的平均温度。可以这么写:

const averageTempJan = 31.9;
const averageTempFeb = 35.3;
const averageTempMar = 42.4;
const averageTempApr = 52;
const averageTempMay = 60.8;

当然,这不是最好的方案,这样只能存一年的数据,要是想多存几年的平均温度呢?我们可以用数组来解决,更简洁的呈现同样的信息

const averageTemp = [];
averageTemp[0] = 31.9;
averageTemp[1] = 35.3;
averageTemp[2] = 42.4;
averageTemp[3] = 52;
averageTemp[4] = 60.8;

(四)创建和初始化数组

在js中创建数组,用[ ]的形式就可以了

例如:

let daysOfWeek = [];

也可以使用一些元素初始化数组

let daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday'];

我们可以使用数组的length属性查看存了多少个元素

console.log(daysOfWeek.length);

运行结果为7

在这里插入图片描述

(五)访问数组和迭代数组

如果要访问数组里特定位置的元素,可以直接使用[ ]传递数值位置,如果我们想要输出daysOfWeek的所有元素,可以通过迭代数组、打印元素

for (let i = 0; i < daysOfWeek.length; i++) {
 console.log(daysOfWeek[i]);
} 

在这里插入图片描述

我们再看另一个例子,求斐波那契数列的前 20 个数。已知斐波那契数列中的前两项是 1,从第三项开始,每一项都等于前两项之和。

const fibonacci = [];
fibonacci[0] = 1;
fibonacci[1] = 1;
for (let i = 2; i < 20; i++) {
 fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
}
for (let i = 0; i < fibonacci.length; i++) {
 console.log(fibonacci[i]);
}

输出结果

在这里插入图片描述

(六)添加元素

假如我们有一个数组 numbers,初始化成了 0 到 9。

let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

我们可以直接给数组最后一位空位赋值

numbers[numbers.length] = 10; 

使用push方法,能把元素添加到数组末尾,通过push方法,我们可以添加任意个元素

numbers.push(11);
numbers.push(12, 13);

下面我们来迭代输出number数组查看结果

for(let i = 0; i < numbers.length; i++){
	console.log(numbers[i])
}

在这里插入图片描述

在数组开头插入元素,使用unshift方法可以直接把数值插入数组的开头

numbers.unshift(-1);
numbers.unshift(-3, -2);

我们再来输出数组

在这里插入图片描述

(七)删除元素

从数组末尾删除元素,使用pop方法

numbers.pop();

输出数组

在这里插入图片描述

删除数组的第一个元素,使用shift方法

numbers.shift();

输出数组

在这里插入图片描述

(八)在任意位置添加和删除元素

使用splice方法,通过指定位置,删除指定数量的元素

numbers.splice(5,3);

输出数组发现,删除了从数组索引 5 开始的 3 个元素,这就意味着 numbers[5]、numbers[6]和numbers[7]从数组中删除了。(3,4,5已经移除)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210503101933384.png)

现在,我们想把数 3、4、5 插入数组里,放到之前删除元素的位置上,可以再次使用 splice方法。

numbers.splice(5, 0, 3, 4, 5);

输出数组

在这里插入图片描述

最后我们可以执行以下代码

numbers.splice(5, 3, 3, 4, 5);

输出的值是从-2 到 12。原因在于,我们从索引 5 开始删除了 3 个元素,但也从索引 5 开始添加了元素 3、4、5。

在这里插入图片描述

(九)二维数组和多维数组

我们把开头的例子改成数天内每小时的温度,要保存两天内的每小时温度数据可以这样写

let averageTemp = [];
averageTemp[0] = [72, 75, 79, 79, 81, 81];
averageTemp[1] = [81, 79, 75, 75, 73, 73]; 

也可以这样写

// day 1
averageTemp[0] = [];
averageTemp[0][0] = 72;
averageTemp[0][1] = 75;
averageTemp[0][2] = 79;
averageTemp[0][3] = 79;
averageTemp[0][4] = 81;
averageTemp[0][5] = 81;
// day 2
averageTemp[1] = [];
averageTemp[1][0] = 81;
averageTemp[1][1] = 79;
averageTemp[1][2] = 75;
averageTemp[1][3] = 75;
averageTemp[1][4] = 73;
averageTemp[1][5] = 73;

创建一个通用函数,看二维数组的输出

function printMatrix(myMatrix) {
	for (let i = 0; i < myMatrix.length; i++) {
		for (let j = 0; j < myMatrix[i].length; j++) {
			console.log(myMatrix[i][j]);
		}
	}
}
printMatrix(averageTemp);

在这里插入图片描述

使用 console.table(averageTemp) 语句,数组结构更清晰

在这里插入图片描述

多维数组

假设我们要创建一个3*3*3的矩阵,每一个格子包含矩阵的i(行)、j(列)及 z(深度)之和

const matrix3x3x3 = [];
for (let i = 0; i < 3; i++) {
	matrix3x3x3[i] = []; // 我们需要初始化每个数组
	for (let j = 0; j < 3; j++) {
		matrix3x3x3[i][j] = [];
		for (let z = 0; z < 3; z++) {
			matrix3x3x3[i][j][z] = i + j + z;
		}
	}
}

输出矩阵内容

for (let i = 0; i < matrix3x3x3.length; i++) {
	for (let j = 0; j < matrix3x3x3[i].length; j++) {
		for (let z = 0; z < matrix3x3x3[i][j].length; z++) {
			console.log(matrix3x3x3[i][j][z]);
		}
	}
}
console.table(matrix3x3x3);

在这里插入图片描述

(十)数组合并

考虑以下场景,有多个数组,需要合并起来成为一个数组。

const zero = 0;
const positiveNumbers = [1, 2, 3];
const negativeNumbers = [-3, -2, -1];

concat 方法可以向一个数组传递数组、对象或是元素。数组会按照该方法传入的参数顺序连接指定数组。

let numbers = negativeNumbers.concat(zero, positiveNumbers);

在这个例子里,zero 将被合并到 nagativeNumbers 中,然后positiveNumbers 继续被合并。

输出数组

for (let i = 0; i < numbers.length; i++){
	console.log(numbers[i])
}

在这里插入图片描述

(十一)迭代器函数

我们需要一个数组和一个函数:假设数组中的值是从 1 到 15;如果数组里的元素可以被 2 整除(偶数),函数就返回 true,否则返回 false。

function isEven(x) {
 // 如果 x 是 2 的倍数,就返回 true
 console.log(x);
 return x % 2 === 0 ? true : false;
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];

其中 return x % 2 === 0 ? true : false; 可以写成 return (x % 2 === 0)

ES6语法可以使用箭头函数来改写isEven函数 const isEven = x => x % 2 === 0;

const isEven = x => x % 2 === 0;
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];

1. 用every迭代

every 方法会迭代数组中的每个元素,直到返回 false。

numbers.every(isEven);

输出结果为1,因为1不是2的倍数,函数返回false,every执行结束

在这里插入图片描述

2. 用some迭代

它和 every 的行为相反,会迭代数组的每个元素,直到函数返回 true。

numbers.some(isEven);

输出结果为1,2,1不是2的倍数返回false。2是2的倍数返回true,some执行结束

在这里插入图片描述

3. 用foreach迭代

numbers.forEach(x => console.log(x % 2 === 0));

在这里插入图片描述

4. 使用map和filter方法

map方法:它保存了传入 map 方法的 isEven函数的运行结果。这样就很容易知道一个元素是否是偶数。

const myMap = numbers.map(isEven);

在这里插入图片描述

filter方法:它返回的新数组由使函数返回 true 的元素组成。

const evenNumbers = numbers.filter(isEven);

在这里插入图片描述

5. 使用reduce方法

reduce 方法接收一个有如下四个参数的函数:previousValue、 currentValue、index 和 array。因为 index 和 array 是可选的参数,所以如果用不到它们的话,可以不传。这个函数会返回一个将被叠加到累加器的值,reduce 方法停止执行后会返回这个累加器。如果要对一个数组中的所有元素求和,这就很有用。

numbers.reduce((previous, current) => previous + current);

在这里插入图片描述

(十二)ES6和数组新功能

1. 使用 for…of 循环迭代

for (const n of numbers) {
	console.log(n % 2 === 0 ? 'even' : 'odd');
}

在这里插入图片描述

2. 使用@@iterator 对象

ES6 还为 Array 类增加了一个@@iterator 属性,需要通过 Symbol.iterator 来访问

iterator = numbers[Symbol.iterator]();
for (const n of iterator) {
 console.log(n);
} 

在这里插入图片描述

3. 数组的 entries、keys 和 values 方法

entries 方法返回包含键值对的@@iterator

aEntries = numbers.entries();
for (const n of aEntries) {
 console.log(n);
} 

在这里插入图片描述

keys 方法返回包含数组索引的@@iterator

const aKeys = numbers.keys(); // 得到数组索引的迭代器
console.log(aKeys.next()); 
console.log(aKeys.next()); 
console.log(aKeys.next()); 

在这里插入图片描述

keys 方法会返回 numbers 数组的索引。一旦没有可迭代的值,aKeys.next()就会返回一个 value 属性为 undefined、done 属性为 true 的对象。如果 done 属性的值为 false,就意味着还有可迭代的值。

values 方法返回的@@iterator 则包含数组的值。

const aValues = numbers.values();
console.log(aValues.next()); 
console.log(aValues.next()); 
console.log(aValues.next()); 

在这里插入图片描述

4. 使用 from 方法

Array.from 方法根据已有的数组创建一个新数组。

例如,要复制 numbers 数组,可以这样做。

let numbers2 = Array.from(numbers);

在这里插入图片描述

还可以传入一个用来过滤值的函数,例如:

let evens = Array.from(numbers, x => (x % 2 == 0));

在这里插入图片描述

5. 使用 Array.of 方法

Array.of 方法根据传入的参数创建一个新数组。

let numbers3 = Array.of(1);
let numbers4 = Array.of(1, 2, 3, 4, 5, 6);

在这里插入图片描述

和下面的代码的效果是一样的

let numbers3 = [1];
let numbers4 = [1, 2, 3, 4, 5, 6];

我们也可以用这个方法来复制已有的数组

let numbersCopy = Array.of(...numbers4);

在这里插入图片描述

6. 使用fill方法

fill 方法用静态值填充数组。

例如:

let numbersCopy = Array.of(1, 2, 3, 4, 5, 6); 
numbersCopy.fill(0);

在这里插入图片描述

输出结果来看数组所有值都会变为0

再比如:

numbersCopy.fill(2, 1);

在这里插入图片描述

输出结果来看数组中从 1 开始的所有位置上的值都是 2

再比如:

numbersCopy.fill(1, 3, 5);

在这里插入图片描述

输出结果来看数组中我们会把 1 填充到数组索引 3 到 5 的位置(不包括 3 和 5)

fill方法在创建数组并且初始化数值的时候非常好用,例如:

let ones = Array(6).fill(1);

在这里插入图片描述

我们创建了一个长度为6,都是1的数组

7. 使用 copyWithin 方法

copyWithin 方法复制数组中的一系列元素到同一数组指定的起始位置。

例如:

let copyArray = [1, 2, 3, 4, 5, 6];

假如我们想把 4、5、6 三个值复制到数组前三个位置,得到[4, 5, 6, 4, 5, 6]这个数组,可以这样做。

copyArray.copyWithin(0, 3);

在这里插入图片描述

从索引3复制后,到索引0

假如我们想把 4、5 两个值(在位置 3 和 4 上)复制到位置 1 和 2,可以这样做:

copyArray.copyWithin(1, 3, 5); 

在这里插入图片描述

这种情况下,会把从位置 3 开始到位置 5 结束(不包括 3 和 5)的元素复制到位置 1,结果是得到数组[1, 4, 5, 4, 5, 6]。

(十三)排序元素

我们想要方向输出之前的数组numbers可以用reverse方法

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
numbers.reverse(); 

在这里插入图片描述

我们再使用sort方法

numbers.sort();

在这里插入图片描述

这样的输出结果因为 sort 方法在对数组做排序时,把元素默认成字符串进行相互比较。

我们可以传入自己写的比较函数。因为数组里都是数,所以可以像下面这样写。

numbers.sort((a, b) => a - b);

意思是: b 大于 a 时,这段代码会返回负数,反之则返回正数。如果相等的话,就会返回 0。也就是说返回的是负数,就说明 a 比 b 小,这样 sort 就能根据返回值的情况对数组进行排序。

也可以写成这样,更清晰

function compare(a, b) {
 if (a < b) {
 return -1;
 }
 if (a > b) {
 return 1;
 }
 // a 必须等于 b
 return 0;
}
numbers.sort(compare);

在这里插入图片描述

1. 自定义排序

例如:

const friends = [{
		name: 'John',
		age: 30
	},
	{
		name: 'Ana',
		age: 20
	},
	{
		name: 'Chris',
		age: 25
	}
];

function comparePerson(a, b) {
	if (a.age < b.age) {
		return -1;
	}
	if (a.age > b.age) {
		return 1;
	}
	return 0;
}
console.log(friends.sort(comparePerson));

在这里插入图片描述

2. 字符串排序

例如:

let names = ['Ana', 'ana', 'john', 'John'];
console.log(names.sort());

在这里插入图片描述

输出根据首字母ASCII 值来比较排序

(十四)搜索

搜索有两个方法:indexOf 方法返回与参数匹配的第一个元素的索引;lastIndexOf 返回与参数匹配的最后一个元素的索引。

我们用到之前的numbers数组

console.log(numbers.indexOf(10));
console.log(numbers.indexOf(100));

在这里插入图片描述

在这个示例中,第一行的输出是 9,第二行的输出是-1(因为 100 不在数组里)。

numbers.push(10);
console.log(numbers.lastIndexOf(10));
console.log(numbers.lastIndexOf(100));

在这里插入图片描述

我们往数组里加入了一个新的元素 10,因此第二行会输出 15(数组中的元素是 1 到 15,还有 10),第三行会输出-1(因为 100 不在数组里)。

1. ES6的find和findIndex方法

let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
function multipleOf13(element, index, array) {
return (element % 13 == 0);
}
console.log(numbers.find(multipleOf13));
console.log(numbers.findIndex(multipleOf13));

在这里插入图片描述

find 和 findIndex 方法接收一个回调函数,搜索一个满足回调函数条件的值。上面的例子里,我们要从数组里找一个 13 的倍数。find 和 findIndex 的不同之处在于,find 方法返回第一个满足条件的值,findIndex方法则返回这个值在数组里的索引。如果没有满足条件的值,find 会返回 undefined,而findIndex 返回-1。

2. ES7 使用 includes方法

如果数组里存在某个元素,includes 方法会返回 true,否则返回 false。

console.log(numbers.includes(15));
console.log(numbers.includes(20)); 

在这里插入图片描述

如果给 includes 方法传入一个起始索引,搜索会从索引指定的位置开始。

let numbers2 = [7,6,5,4,3,2,1];
console.log(numbers2.includes(4,5));

在这里插入图片描述

上面的例子输出为 false,因为数组索引 5 之后的元素不包含 4。

(十五)输出数组为字符串

toString 和 join方法

例如:

let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
const numbersString = numbers.join('-');
console.log(numbersString); 

在这里插入图片描述

如果要把数组内容发送到服务器,或进行编码(知道了分隔符,解码也很容易),这会很有用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值