1. 数组概述
1.1 定义:
数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。
注意:任何类型的数据,都可以放入数组,可以是(数字,字符,布尔值,对象,数组,函数);如果数组的元素还是数组,就形成了多维数组。
数组有两种定义方式:
- 先定义,后赋值:代码所示
var arr=new Array();//创建一个空的数组,由于数组是对象,因此创建数组需要使用new运算符
//数组的索引值是从零开始的;
var arr=new Array(5);//创建一个长度为5的数组(有5个储存空间);
arr[0]=10;//arr[索引值]数组中对应的储存空间;
arr[1]=20;//索引值就是数组中每个值的位置对应的编号;从零开始;
arr[2]=30;
arr[3]=40;
arr[4]=50;
console.log(arr);
- 定义的时候赋值,代码所示:
var arr=[10,20,30,40,50];
//arr.length=5
1.2 数组的本质
本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。
typeof ([1, 2, 3]); //object 上面代码表明,typeof运算符认为数组的类型就是对象,因此创建数组需要使用new运算符。
1.3 数组的特点
- 数组是值的有序集合
- 由于弱类型的原因,JavaScript中数组十分灵活、强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素。
- js数组长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改。
1.4 数组的基本要素
- 标识符:就是数组的名称,用于区分不同的数组 ;
- 数组元素:即向数组中存放的数据;
- 元素下标(索引值):对数组元素进行编号,从0开始,数组中的每个元素都可以通过下标来访问 ;
- 数组长度,length属性表示数组的长度,即数组中元素的个数;
1.5 for...in 循环和数组的遍历
for...in循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象。
var a = [1, 2, 3];
for (var i in a) {
console.log(a[i]);
}// 1 2 3数组的遍历可以考虑使用for循环或while循环。
var a = [1, 2, 3];
// for循环
for(var i = 0; i < a.length; i++) {
console.log(a[i]);
}
// while循环
var i = 0;
while (i < a.length) {
console.log(a[i]);
i++;
}
var l = a.length;
while (l--) {
console.log(a[l]);
}1.6 二维数组
二维数组:一维数组内容还是数组;代码所示;
<script>
var arr=[[11,22,33],[44,55,66],[77,88,99]];
// console.log(arr[0][1]);
// 遍历二维数组
for(var n=0;n<arr.length;n++){ //外层循环拿到二维数组中的一维数组;
for(var j=0;j<arr[n].length;j++){
console.log(arr[n][j]); //遍历指定一维数组;
}
}
</script>
2. 数组的基本处理函数
先来看一个需求:var arr=[11,22,33,44];在这个数组的第一个位置添加一个元素10;
var arr=[11,22,33,44];
for(n=arr.length;n>=0;n--){
//需要开辟一个新的空间出来,将原有的值向后移动一位,
//到第一个位置时,让值等于要插入的元素;
if (n==0) {
arr[0]=10;
}else{
arr[n]=arr[n-1];
}
}
console.log(arr);显然,如果这么做会很麻烦,所以我们来学习一些函数;
2.1 Array 对象方法
| 方法 | 描述 |
|---|---|
| concat() | 连接两个或更多的数组,并返回结果。 |
| join() | 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 |
| pop() | 删除并返回数组的最后一个元素 |
| push() | 向数组的末尾添加一个或更多元素,并返回新的长度。 |
| reverse() | 颠倒数组中元素的顺序。 |
| shift() | 删除并返回数组的第一个元素 |
| slice() | 从某个已有的数组返回选定的元素 |
| sort() | 对数组的元素进行排序 |
| splice() | 删除元素,并向数组添加新元素。 |
| toSource() | 返回该对象的源代码。 |
| toString() | 把数组转换为字符串,并返回结果。 |
| toLocaleString() | 把数组转换为本地数组,并返回结果。 |
| unshift() | 向数组的开头添加一个或更多元素,并返回新的长度。 |
| valueOf() | 返回数组对象的原始值 |
2.1.1 末尾添加 .push() 末尾删除 .pop() 开头添加 .unshift() 开头删除 .shift()
- push() 在数组的末尾添加一个或多个元素(多个元素时,用逗号隔开);并且返回新数组的长度; 返回:就是执行完等于什么;
var arr=[11,22,33,44,55]; var x=arr.push(66,77); console.log(arr); console.log(x); - pop() 删除最后一个元素,返回被删除的元素;
var arr=[11,22,33,44,55]; var z=arr.pop(); console.log(arr); console.log(z); - unshift() 在数组的开头添加一个或多个元素(多个元素时,用逗号隔开);并且返回新数组的长度;
var arr=[11,22,33,44,55]; var y=arr.unshift(8,10); console.log(arr); console.log(y); - shift() 删除第一个元素,并且返回被删除的元素;
var arr=[11,22,33,44,55]; var x=arr.shift(); console.log(arr); console.log(x);
2.1.2 splice() 删除指定的元素,或在指定的位置添加元素
(需求:想要在数组 var arr=[11,22,33,44,55]; 第二个位置添加新内容;)
splice() 有两个作用
- 第一个作用:如果括号中只有两个参数,是删除指定元素 ;返回被删除的元素 其中,第一个参数:发生变化的位置; 第二个参数:向后删除几个元素。
var arr=[11,22,33,44,55]; var x=arr.splice(1,1); console.log(arr);//4) [11, 33, 44, 55] console.log(x);//[22] - 第二个作用:如果有三个参数,是添加(或插入)元素 前两个参数作用不变,第三个以及以后的参数,是要添加的元素;返回被删除的元素;
var arr=[11,22,33,44,55]; var x=arr.splice(1,1,99); console.log(arr);//[11, 99, 33, 44, 55] console.log(x);//[22]
2.1.3 concat() 数组合并
将两个或多个数组合并,然后返回出来,不会改变原始数组;
var arr1=[11,22,33];
var arr2=[44,55,66];
var arr3=[77,88,99];
var x=arr1.concat(arr2,arr3);
console.log(x); 2.1.4 indexOf()和.lastIndexOf() 检测指定元素是否在数组
(需求:检测指定元素是否在数组中)
.indexOf() 检测指定元素是否在数组中,如果在,返回第一次出现位置(即元素所在的下标),如果不在,返回-1;
var arr1=[12,23,54,12,65];
var x=arr1.indexOf(12);
console.log(x);
lastIndexOf() 检测指定元素是否在数组中,如果在,返回最后一次出现位置(即元素所在的下标),如果不在,返回-1;
var arr1=[12,23,54,12,65];
var x=arr1.lastIndexOf(12);
console.log(x);
console.log(typeof(arr)); 2.1.5 sort() 数组的排序
sort() 方法用于对数组的元素进行排序。语法:
arrayObject.sort(sortby)| 参数 | 描述 |
|---|---|
| sortby | 可选。规定排序顺序。必须是函数。 |
返回值:对数组的引用。请注意,数组在原数组上进行排序,不生成副本。
说明:如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
- 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
- 若 a 等于 b,则返回 0。
- 若 a 大于 b,则返回一个大于 0 的值。
var arr1=[12,23,54,12,65];
arr1.sort();
console.log(arr1); 2.1.6 reverse() ,数组倒置(将数组中的内容 颠倒一下 ),返回倒置后的数组
var arr1=[12,23,54,12,65];
arr1.reverse();
console.log(arr1); 2.1.7 join()
.join()是通过指定的字符,将数组变成字符串,返回出来
join(参数)用参数链接数组中的元素,如果参数不写的话默认是逗号;
var arr1=[12,23,54,12,65];
var str=arr.join("*");
console.log(str);
console.log(typeof(str)); 2.1.8 map()
.map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
array.map(function(elem, index, arr), thisValue)map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。
var numbers = [1, 2, 3];
numbers.map(function (n) {
return n + 1;
});
// [2, 3, 4]
numbers
// [1, 2, 3]
上面代码中,numbers数组的所有成员依次执行参数函数,运行结果组成一个新数组返回,原数组没有变化。
map方法接受一个函数作为参数。该函数调用时,map方法向它传入三个参数:当前成员、当前位置和数组本身。
[1, 2, 3].map(function(elem, index, arr) {
return elem * index;
});
// [0, 2, 6]
上面代码中,map方法的回调函数有三个参数,elem为当前成员的值,index为当前成员的位置,arr为原数组([1, 2, 3])。
map方法还可以接受第二个参数,用来绑定回调函数内部的this变量(详见《this 变量》一章)。
var arr = ['a', 'b', 'c'];
[1, 2].map(function (e) {
return this[e];
}, arr)
// ['b', 'c']
上面代码通过map方法的第二个参数,将回调函数内部的this对象,指向arr数组。
如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位。
var f = function (n) { return 'a' };
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
[1, '', 2].map(f) //["a", "a", "a"]上面代码中,map方法不会跳过undefined和null,但是会跳过空位。
实例2:求数组中每个元素的平方根
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
/* roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9] */实例3:将下边两个字符串拼接成["A1", "A2", "A", "B1", "B2", "B", "C1", "C2", "C", "D1", "D2", "D"]
var arr1 = ['A', 'B', 'C', 'D'];
var arr2 = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2'];
var x = arr1.map( elem => elem + 3)
var y = x.concat(arr2).sort().map( elem => elem.replace(/3/g , "") )
//(12) ["A1", "A2", "A", "B1", "B2", "B", "C1", "C2", "C", "D1", "D2", "D"]2.1.9 slice() 方法
slice方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
arr.slice(start, end);
它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员。
var a = ['a', 'b', 'c'];
a.slice(0) // ["a", "b", "c"]
a.slice(1) // ["b", "c"]
a.slice(1, 2) // ["b"]
a.slice(2, 6) // ["c"]
a.slice() // ["a", "b", "c"]
上面代码中,最后一个例子slice没有参数,实际上等于返回一个原数组的拷贝。
如果slice方法的参数是负数,则表示倒数计算的位置。
var a = ['a', 'b', 'c'];
a.slice(-2) // ["b", "c"]
a.slice(-2, -1) // ["b"]
上面代码中,-2表示倒数计算的第二个位置,-1表示倒数计算的第一个位置。
如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。
var a = ['a', 'b', 'c'];
a.slice(4) // []
a.slice(2, 1) // []
slice方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));
Array.prototype.slice.call(arguments);
上面代码的参数都不是数组,但是通过call方法,在它们上面调用slice方法,就可以把它们转为真正的数组。
var arr = new Array(3);
arr[0] = "George";
arr[1] = "John";
arr[2] = "Thomas";
document.write(arr + "<br />");
document.write(arr.slice(1) + "<br />");
document.write(arr);
//George,John,Thomas
//John,Thomas
//George,John,Thomas实例:数组拆分的函数
function sliceArray(array, size) {
var result = [];
for (var x = 0; x < Math.ceil(array.length / size); x++) {
var start = x * size;
var end = start + size;
result.push(array.slice(start, end));
}
return result;
}let pages = [];
array.forEach((item,index) => {
let x = parseInt(index/8);
if (!pages[x]) {
pages[x] = [];
}
pages[x].push(item);
})
console.log(pages)2.1.10 forEach() 方法
forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。
forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。
function log(element, index, array) {
console.log('[' + index + '] = ' + element);
}
[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9
上面代码中,forEach遍历数组不是为了得到返回值,而是为了在屏幕输出内容,所以不必使用map方法。
forEach方法也可以接受第二个参数,绑定参数函数的this变量。
var out = [];
[1, 2, 3].forEach(function(elem) {
this.push(elem * elem);
}, out);
out // [1, 4, 9]
上面代码中,空数组out是forEach方法的第二个参数,结果,回调函数内部的this关键字就指向out。
注意,forEach方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用for循环。
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
if (arr[i] === 2) break;
console.log(arr[i]);
}
// 1
上面代码中,执行到数组的第二个成员时,就会中断执行。forEach方法做不到这一点。
forEach方法也会跳过数组的空位。
var log = function (n) {
console.log(n + 1);
};
[1, undefined, 2].forEach(log)
// 2
// NaN
// 3
[1, null, 2].forEach(log)
// 2
// 1
// 3
[1, , 2].forEach(log)
// 2
// 3
上面代码中,forEach方法不会跳过undefined和null,但会跳过空位。
2.1.11 filter() 方法
filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。
它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
[1, 2, 3, 4, 5].filter(function (elem) {
return (elem > 3);
})
// [4, 5]
上面代码将大于3的数组成员,作为一个新数组返回。
var arr = [0, 1, 'a', false];
arr.filter(Boolean)
// [1, "a"]
上面代码中,filter方法返回数组arr里面所有布尔值为true的成员。
filter方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。
[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
return index % 2 === 0;
});
// [1, 3, 5]
上面代码返回偶数位置的成员组成的新数组。
filter方法还可以接受第二个参数,用来绑定参数函数内部的this变量。
var obj = { MAX: 3 };
var myFilter = function (item) {
if (item > this.MAX) return true;
};
var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj) // [8, 4, 9]
上面代码中,过滤器myFilter内部有this变量,它可以被filter方法的第二个参数obj绑定,返回大于3的成员。
2.1.12 reduce( ) 和 reduceRight()
定义: reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
语法:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。
[1, 2, 3, 4, 5].reduce(function (a, b) {
console.log(a, b);
return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15
上面代码中,reduce方法求出数组所有成员的和。第一次执行,a是数组的第一个成员1,b是数组的第二个成员2。第二次执行,a为上一轮的返回值3,b为第三个成员3。第三次执行,a为上一轮的返回值6,b为第四个成员4。第四次执行,a为上一轮返回值10,b为第五个成员5。至此所有成员遍历完成,整个方法的返回值就是最后一轮的返回值15。
reduce方法和reduceRight方法的第一个参数都是一个函数。该函数接受以下四个参数。
- 累积变量,默认为数组的第一个成员(必选)
- 当前变量,默认为数组的第二个成员(必选)
- 当前位置(从0开始)(可选)
- 原数组(可选)
reduce方法 第二个参数,(可选)
| initialValue | 可选。传递给函数的初始值 |
这四个参数之中,只有前两个是必须的,后两个则是可选的。
如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25
上面代码指定参数a的初值为10,所以数组从10开始累加,最终结果为25。注意,这时b是从数组的第一个成员开始遍历。
上面的第二个参数相当于设定了默认值,处理空数组时尤其有用。
function add(prev, cur) {
return prev + cur;
}
[].reduce(add)
// TypeError: Reduce of empty array with no initial value
[].reduce(add, 1)
// 1
上面代码中,由于空数组取不到初始值,reduce方法会报错。这时,加上第二个参数,就能保证总是会返回一个值。
下面是一个reduceRight方法的例子。
function subtract(prev, cur) {
return prev - cur;
}
[3, 2, 1].reduce(subtract) // 0
[3, 2, 1].reduceRight(subtract) // -4
上面代码中,reduce方法相当于3减去2再减去1,reduceRight方法相当于1减去2再减去3。
由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, '');
}
findLongest(['aaa', 'bb', 'c']) // "aaa"
上面代码中,reduce的参数函数会将字符长度较长的那个数组成员,作为累积值。这导致遍历所有成员之后,累积值就是字符长度最长的那个成员。
2. 数组去重
方法一:
var arr=[11,22,33,44,55,22,22,33,54];//拿到数组中不重复的元素
var x=[]; //定义一个空数组
for(var n=0;n<arr.length;n++){
if (x.indexOf(arr[n])==-1){
x.push(arr[n]);//怎么判断新的数组中是否有arr[n]这个元素呢;
}
}
console.log(x.sort());方法二:
var arr=[11,22,33,44,55,22,33,54];
for(var n=0;n<arr.length;n++){
for(var j=n+1;j<arr.length;j++){
if (arr[n]==arr[j]) {
arr.splice(arr.indexOf(arr[j]),1);
j--;
}
}
}
console.log(arr)
方法三:
var arr=[11,22,33,44,55,22,33,54];
for(var n=0;n<arr.length;n++){
if (arr.indexOf(arr[n])!=arr.lastIndexOf(arr[n])){
//判断arr[n]出现的次数,如果次数不是一次,那么删除后边的元素
arr.splice(arr.lastIndexOf(arr[n]),1);
n--;//没有这个n--,相当于执行了8次,
}
}
console.log(arr);如果没有n--
var arr=[11,22,33,33,33,44,55,22,22,33,54,33];
// [11,22,33,33,33,44,55,22,22,33,54,33]第1次执行 12 n=0
// [11,22,33,33,33,44,55,22,33,54,33]第2次执行 11 n=1
// [11,22,33,33,33,44,55,22,33,54]第3次执行 10 n=2
// [11,22,33,33,44,55,22,54]第4次执行 n=3
// [11,22,33,33,44,55,22,54]第5次执行 n=4
// [11,22,33,33,44,55,22,54]第6次执行 n=5
// [11,22,33,33,44,55,54]第7次执行 n=6
// [11,22,33,33,44,55,54]第8次执行 n=7
有了n--
var arr=[11,22,33,33,33,44,55,22,22,33,54,33];
// (10)[11, 22, 33, 33, 33, 44, 55, 22, 22, 33, 54, 33] n=0时执行,执行完之后 n=0
// (11) [11, 22, 33, 33, 33, 44, 55, 22, 33, 54, 33] n=1时执行,执行完之后 n=0
// (10) [11, 22, 33, 33, 33, 44, 55, 33, 54, 33] n=1时执行,执行完之后 n=0
// (10) [11, 22, 33, 33, 33, 44, 55, 33, 54, 33] n=1时执行,执行完之后 n=1
// (9) [11, 22, 33, 33, 33, 44, 55, 33, 54] n=2时执行,执行完之后 n=1
// (8) [11, 22, 33, 33, 33, 44, 55, 54] n=2时执行,执行完之后 n=1
// (7) [11, 22, 33, 33, 44, 55, 54] n=2时执行,执行完之后 n=1
// (6) [11, 22, 33, 44, 55, 54] n=2时执行,执行完之后 n=1
// (6) [11, 22, 33, 44, 55, 54] n=2时执行,执行完之后 n=2
// (6) [11, 22, 33, 44, 55, 54] n=3时执行,执行完之后 n=3
// (6) [11, 22, 33, 44, 55, 54] n=4时执行,执行完之后 n=4
// (6) [11, 22, 33, 44, 55, 54] n=5时执行,执行完之后 n=53. 数组排序
3.1 sort排序法
(1)简单数组的简单排序
var arrSimple=new Array(1,8,7,6);
arrSimple.sort();
console.log(arrSimple.join()) ;复制代码(2)简单数组的自定义排序
var arrSimple2=new Array(1,8,7,6);
arrSimple2.sort(function(a,b){
return a-b
});
console.log(arrSimple2.join())复制代码(3)简单对象 List 自定义属性排序
var objectList = new Array();
function Persion(name,age){
this.name=name;
this.age=age;
}
objectList.push(new Persion('jack',20));
objectList.push(new Persion('tony',25));
objectList.push(new Persion('stone',26));
objectList.push(new Persion('mandy',23));
//按年龄从小到大排序
objectList.sort(function(a,b){
return a.age-b.age
});
for(var i=0;i<objectList.length;i++){
document.writeln('<br />age:'+objectList[i].age+' name:'+objectList[i].name);
}复制代码var objectList2 = new Array();
function WorkMate(name,age){
this.name=name;
var _age=age;
this.age=function(){
if(!arguments){
_age=arguments[0];
}else{
return _age;
}
}
}
objectList2.push(new WorkMate('jack',20));
objectList2.push(new WorkMate('tony',25));
objectList2.push(new WorkMate('stone',26));
objectList2.push(new WorkMate('mandy',23));
//按年龄从小到大排序
objectList2.sort(function(a,b){
return a.age()-b.age();
});
for(var i=0;i<objectList2.length;i++){
document.writeln('<br />age:'+objectList2[i].age()+' name:'+objectList2[i].name);
}复制代码3.2 冒泡排序法
解析:1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。
2.第一轮的时候最后一个元素应该是最大的一个。
3.按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较)(所以减 i )。
var arr=[7,20,3,8,4,9,4,0,-4,1]
function sort(elements){
for(var i=0;i<elements.length-1;i++){
for(var j=0;j<elements.length-i-1;j++){
if(elements[j]>elements[j+1]){
var swap=elements[j];
elements[j]=elements[j+1];
elements[j+1]=swap;
}
}
}
}
console.log("before:"+arr)//before:[7,20,3,8,4,9,4,0,-4,1]
sort(arr);
console.log("after:"+arr) //after:-4,0,1,3,4,4,7,8,9,20复制代码二维数组使用冒泡排序
方法1:
var arr=[["北京",80],["上海",50],["福州",10],["广州",50],["成都",70],["西安",100]];
var t;
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-1;j++){
if(arr[j][1]>arr[j+1][1]){
t=arr[j][1];
arr[j][1]=arr[j+1][1];
arr[j+1][1]=t;
}
}
}
console.log(arr);
//["福州",10],["上海",50],["广州",50],["成都",70],["北京",80],["西安",100]复制代码方法2:(选择排序法)
var arr=[["北京",80],["上海",50],["福州",10],["广州",50],["成都",70],["西安",100]];
for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i][1]>arr[j][1]){
var t=arr[j][1];
arr[j][1]=arr[i][1];
arr[i][1]=t;
}
}
}
console.log(arr); 复制代码冒泡排序动图:
3.3 选择排序法
var array = [1,4,-8,-3,6,12,9,8];
function selectSort(arr){
for(var i=0;i<arr.length;i++){
//设置当前范围最小值和索引
var min = arr[i];
var minIndex = i;
//在该范围选出最小值
for(var j=i+1;j<arr.length;j++){
if(min>arr[j]){
min = arr[j];
minIndex = j;
}
}
//将最小值插入,并将原来位置的最小值删除
arr.splice(i,0,min);
arr.splice(minIndex+1,1);
}
}
selectSort(array);
document.write(array);复制代码- (1)在未排序序列中找到最小(大)元素
- (2)并存放到排序序列的起始位置
- (3)然后,再从剩余未排序元素中继续寻找最小(大)元素
- (4)然后放到已排序序列的末尾。
- (5)以此类推
选择排序动图
4. 练习题
4.1 求数组 var arr=[10,20,30,40,50];的总分和平均分;
<script>
var arr=[10,20,30,40,50];
var sum=0;
var average=0;
for(var n=0;n<arr.length;n++){
sum=sum+arr[n];
average=sum/arr.length;
}
console.log(sum);
console.log(average);
</script>
4.2 一个数组中求最大(小)值-并且找出其位置;
<script> //最大值
var arr=[11,22,33,44,88,66];
var max=arr[0]; //假设max为数组中的第一个数,且是最大的
var index=0; //思想:假设index为数组中第一个数的位置编号(索引值)
for(var n=1;n<arr.length;n++){
if (arr[n]>max) { //检测后边数组中有没有比他大的数
max=arr[n]; //有的话,就让max重新赋值为比他大的数;
index=n; //index等于比他大的数的位置
}
}
console.log(max);
console.log(index);
</script>
<script>
var arr=[11,22,33,44,88,66];
var min=arr[0];
var index=0;
for(n=1;n<arr.length;n++){
if (arr[n]<min) {
min=arr[n];
index=n;
}
}
console.log(min);
console.log(index);
</script>
4.3 对数组进行排序 (选择排序法 或者 冒泡排序法)
var arr=[21,23,18,96,15,56,85,52,12];
<script>
//从大到小进行排序 拿出第一个数与后边的数进行比较,
//选出最大的一个数,然后再拿第二个数与后边的数进行比较;
//1.选择排序法
var arr=[21,23,18,96,15,56,85,52,12];
for(var n=0;n<arr.length;n++){ //依次拿到数组中的数
for(var j=n+1;j<arr.length;j++){ //拿到后面的数
if (arr[j]>arr[n]) { //如果后边的数比前面的数大,就交换位置
var t=arr[n];
arr[n]=arr[j];
arr[j]=t;
}
}
}
console.log(arr)
</script>
4.4 级联列表 用JS实现下拉列表
<body>
<select name="" id="bt1"></select>
<select name="" id="bt2"></select>
<script>
//默认样式, 静态样式
var arr=["河北","河南","山东","北京"];//定义一个省份数组
//然后利用遍历数组,把数组放到对应的select中;
var str="";
for(var n=0;n<arr.length;n++){
str=str+"<option>"+arr[n]+"</option>";
}
var bt1=document.getElementById("bt1");
bt1.innerHTML=str;
var city=[["秦皇岛","石家庄","唐山"],["许昌","郑州","洛阳"],["青岛","济南","淄博"],["西城","朝阳","海淀"]];
//定义一个二维数组,放置省份对应的市区,
//由于默认显示的是河北,所以第二个下拉列表中需要显示河北对应的市区;
//所以要遍历city数组中第一个小数组;
var str1="";
for(var j=0;j<city[0].length;j++){
str1=str1+"<option>"+city[0][j]+"</option>";
}
var bt2=document.getElementById("bt2");
bt2.innerHTML=str1;
//JS交互
//需求:当第一个下拉列表发生变化时,第二个下拉列表随之发生变化;
//onclick 点击事件 onchange 改变事件,当内容发生变化时,触发函数;
//思路:1.找到当前改变后的位置;
// 2.遍历对应的数组;
// 3.拼接字符串,插入到bt2中;
bt1.onchange=function(){
// console.log("触发了");
var index=bt1.selectedIndex;//bt1中,当前选中option位置的索引值;
//问题:为什么要拿到对应的位置? 因为需要找到其对应的小数组的位置;
console.log("index="+index);
var str2="";
for(n=0;n<city[index].length;n++){
str2=str2+"<option>"+city[index][n]+"</option>";
}
bt2.innerHTML=str2;
}
</script>
</body>
4.5 级联列表-图片
我们第五题的基础上,加入图片;当第一个下拉列表发生变化时,第二个下拉列表随之发生变化;对应的图片也发生变化。
<body>
省份:<select name="" id="bt1"></select>
市:<select name="" id="bt2"></select>
<img src="" alt="" id="img">;
<script>
var arr=["河南","河北","山东","北京"];
var str="";
for(var n=0;n<arr.length;n++){
str=str+"<option>"+arr[n]+"</option>";
}
var bt1=document.getElementById("bt1");
bt1.innerHTML=str;
var city=[["许昌","郑州","洛阳"],["秦皇岛","石家庄","邢台"],["青岛","济南","日照"],["西城","东城","海淀"]];
//将图片的地址保存在数组里;保持一一对应关系
var image=[["图片.jpg",".jpg","jpg"],["1","2","3"],["4","5","6"],["7","8","9"]];
var str1="";
for(var j=0;j<city[0].length;j++){
str1=str1+"<option>"+city[0][j]+"</option>";
}
var bt2=document.getElementById("bt2");
bt2.innerHTML=str1;
//显示到默认的图片
var img=document.getElementById("img");
img.src=image[0][0];
bt1.onchange=function(){
var index=bt1.selectedIndex;
console.log("indnx"+index);
var str2="";
for(i=0;i<city[index].length;i++){
str2=str2+"<option>"+city[index][i]+"</option>";
}
bt2.innerHTML=str2;//改变到指定的图片
//image[index]找到对应的图片数组
////由于切换时永远显示第一张图片,那么直接将地址换成数组中的第一项;
img.src=image[index][0];
bt2.onchange=function(){
var index=bt1.selectedIndex;//找到对应的大(一维)数组中的位置
var index0=bt2.selectedIndex;//找到对应的小(二维)数组中的位置
console.log("tp"+index0);
img.src=image[index][index0];//根据数组及其位置,找到对应的图片;
}
}
</script>
</body>
4.6 三级联动
<body>
省:<select name="" id="bt1"></select>
市:<select name="" id="bt2"></select>
区:<select name="" id="bt3"></select>
<img src="" alt="" id="img">;
<script>
var arr=["河北省","湖北省","河南省","山东省"];
var city=[["秦皇岛市","石家庄市","保定市"],["武汉市","襄阳市","宜昌市"],
["郑州市","许昌市","洛阳市"],["青岛市","济南市","日照市"]];
var district=[[["海港区","抚宁区","开发区"],["长安区","桥西区","新华区"],
["竞秀区","莲池区","满城区"]],[["洪山区","汉口区","武昌区"],["襄城区","樊城区","襄州区"],
["西陵区","伍家岗区","点军区"]],[["中原区","二七区","金水区"],["禹州市","长葛市","郏县"],
["涧西区","西工区","洛龙区"]],[["市南区","市北区","黄岛区"],["历下区","市中区","槐荫区"],
["日照区","东港区","岚山区"]]];
var image=[[["","",""],["", "",""],["","",""]],[["","",""],["","",""],["","",""]],
[["","",""],["","",""],["","",""]],[["","",""],["","",""],["","",""]]];
var str="";
for(n=0;n<arr.length;n++){
str+="<option>"+arr[n]+"</option>";
}
var bt1=document.getElementById("bt1");
bt1.innerHTML=str;
var str1="";
for(j=0;j<arr[0].length;j++){
str1+="<option>"+city[0][j]+"</option>";
}
var bt2=document.getElementById("bt2");
bt2.innerHTML=str1;
var str3="";
for(q=0;q<district[0][0].length;q++){
str3+="<option>"+district[0][0][q]+"</option>";
}
var bt3=document.getElementById("bt3");
bt3.innerHTML=str3;
var img=document.getElementById("img");
img.src=image[0][0][0];
//添加JS动态交互
bt1.onchange=function(){
var index=bt1.selectedIndex;//获取到bt1变化后的索引值;
var str2="";
for(i=0;i<city[index].length;i++){
str2+="<option>"+city[index][i]+"</option>";
}
var bt2=document.getElementById("bt2");
bt2.innerHTML=str2;
str4="";
for(e=0;e<district[index][0].length;e++){
str4+="<option>"+district[index][0][e]+"</option>";
}
var bt3=document.getElementById("bt3");
bt3.innerHTML=str4;
img.src=image[index][0][0];
bt2.onchange=function(){
var index=bt1.selectedIndex;
var index1=bt2.selectedIndex;//获取bt2变化后的索引值;
console.log("p"+index1);
var str5="";
for(t=0;t<district[index][index1].length;t++){
str5+="<option>"+district[index][index1][t]+"</option>";
}
bt3.innerHTML=str5;
bt3.onchange=function(){
var index=bt1.selectedIndex;
var index1=bt2.selectedIndex;
var index2=bt3.selectedIndex;
console.log("x"+index2);
img.src=image[index][index1][index2];
}
}
}
</script>
</body>