JavaScript Array 对象与排序
API:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
javaScript的Array对象是用于构造数组的全局对象,数组类似于列表的高阶对象。在javaScript的数组中,元素没有任何限制 , 可以保存所有类型,如:
var a = [ 'test', 123, false, [1,3,3], {id: 1, value: 3}, null, undefined ]
创建数组:
方式一:使用new操作符
var arr = new Array(5); //指定数组长度,但打印数组时,每一位上都是undefined //注意是使用new Array时,若只有一个参数时表示的是数组的长度
var arr = new Array(5,3); //数组里保存了两个元素 5 和 3
方式二:
var arr = [1,2,3];//这种方式更为常见
数组的长度,Array.length
在普通编程语言当中(如:java),数组长度是不可变的,而在JS当中,数组长度是可变的,删除元素,添加元素,不需要关心长度,它会自动变化。这种特性产生了对数组长度的一些用法,如:
// 清空数组 arr.length = 0 // 截取数组前n个元素 arr.length = n
数组为什么是object类型?
JS是面相对象的语言,JS数组的本质,就是对象。 对象的本质,是哈希。 哈希的本质是数组
//原理: 在JS中,数组实际上是一个做了特殊处理的对象 var obj = { "0" : 1, "1" : 2, "2" : 3, "3" : 4, "length" : 4 }
那么我们同样可以使用循环进行遍历
for(var i=0; i<obj.length; i++) { console.log(obj[i]); }
简单的说,引用类型,即传入的参数是对象就放在堆里(栈里放的是堆的指针);数值类型,不是对象就放在栈里
数组的默认排序,sort方法(说明 http://www.w3school.com.cn/jsref/jsref_sort.asp)
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
- 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
- 若 a 等于 b,则返回 0。
- 若 a 大于 b,则返回一个大于 0 的值。
/*按照对象的年龄从大到小进行排序*/ function Man(name,age){ this.name=name; this.age=age; } var mans=[]; mans.push(new Man("小明",14)); mans.push(new Man("小红",28)); mans.push(new Man("小刚",19)); mans.sort(function(a,b){ return b.age-a.age; }); console.log(mans);
打乱原有数组
var list = [1, 2, 3, 63, 85, 24, 87, 95, 43]
var newList = list.sort( () => Math.random() - 0.5);
如何判断某变量是否为数组数据类型?
方法一.判断其是否具有“数组性质”,如push()方法。由于自己也可以给该变量定义push方法,所以这种方式并不准确
方法二.obj instanceof Array在某些IE版本中不正确
方法三.方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(),保证其兼容性,最好的方法如下:
if(typeofArray.isArray==="undefined"){ Array.isArray = function(arg){ return Object.prototype.toString.call(arg)==="[object Array]" } }
冒泡排序算法
function select(arr){//冒泡排序 for(var i=0;i<arr.length-1;i++){ for(var j=0;j<arr.length-i;j++){ if(arr[j]>arr[j+1]){ var t=arr[j]; arr[j]=arr[j+1]; arr[j+1]=t; } } console.log(arr); } } select([12,9,38,44,98,7,35,59,49,88,38]);
选择排序算法
function select(arr){//选择排序 for(var i=0;i<arr.length-1;i++){ for(var j=i+1;j<arr.length;j++){ if(arr[i]>arr[j]){ var t=arr[i]; arr[i]=arr[j]; arr[j]=t; } } console.log(arr); } } select([12,9,38,44,98,7,35,59,49,88,38]);
快速排序法
function quick_sort(arr){//快速排序 if(arr.length<=1)return arr;//当传入的数组长度为1或0时跳出 var midIndex=parseInt(arr.length/2);//中间值索引 var midValue=arr[midIndex];//中间值 var left=[];//比中间值小的放左边 var right=[];//比中间值大或等于的放右边 for(var i in arr){ if(i==midIndex)continue;//跳过中间值 arr[i]<midValue?left.push(arr[i]):right.push(arr[i]); } return quick_sort(left).concat(midValue,quick_sort(right));//返回结果 } console.log(quick_sort([12,9,38,44,98,7,35,59,49,88,38]));
取末尾值作为基准
function quickSort (arr) { let len = arr.length; if (len <= 1) { return arr; } let value = arr[len -1]; // 获取最后一位数 let left = [], right = []; for (let i = 0; i < len - 1; i++) { let tmp = arr[i]; value > tmp ? left.push(tmp) : right.push(tmp); } return quickSort(left).concat(value, quickSort(right)); }
索引法
function quickSort (arr) { function swap (a, i, j) { let tmp = a[i]; a[i] = a[j]; a[j] = tmp; } function sort (a, i, j) { if (i >= j) { return; } let beg = i; let end = j; while (i + 1 <= j) { if (a[i] > a[i + 1]) { swap(a, i, i + 1); i ++; } else { swap(a, i + 1, j); j --; } } sort(a, beg, i - 1); sort(a, j + 1, end); } sort(arr, 0, arr.length - 1); return arr; }
插入排序
当前元素的前面如果已经没有元素,则无需插入。
如果要插入的元素 < 前一个元素,则进行交换。
依次类推
View Code
View Code
var list =[12,9,38,44,98,7,35,59,49,88,38]; function insertSort(arr){ for(var i=0; i<arr.length; i++){ var n = i; while( arr[n] < arr[n-1] && n-1>=0 ){ var temp = arr[n]; arr[n] = arr[n-1]; arr[n-1] = temp; n--; } } return arr; }
function insert_sort(arr){//插入排序 for(var i=0;i<arr.length;i++){ for(var j=i;j>0;j--){ if(arr[j]<arr[j-1]){ var tmp=arr[j]; arr[j]=arr[j-1]; arr[j-1]=tmp; }else{ break; } } console.log(arr); } } console.log(insert_sort([12,9,38,44,98,7,35,59,49,88,38]));
希尔排序
var list =[12,9,38,44,98,7,35,59,49,88,38]; function shell(arr){ var interval = parseInt(arr.length/2); //定义一个间隔 while(interval>=1){ console.log("间隔"+interval); for(var i=0; i<arr.length; i++){ //插入排序 var index = i; while(arr[index] < arr[index-interval] && index-interval>=0){ //按照间隔做插入排序 //交换 [arr[index], arr[index-interval]] = [arr[index-interval], arr[index]]; index -= interval; } } console.log("结果: "+arr); interval = parseInt(interval/2); } return arr; }
function shell_sort(arr){//希尔排序 for(var j=parseInt(arr.length/2);j>=1;j=parseInt(j/2)){//j为步长,一般来说步长的确定没有严格的要求,但必须有为1的步长 for(var i=j;i<arr.length;i++){// 遍历数组 for(var k=i;k>0;k-=j){//对间隔为步长的元素进行插入排序 if(arr[k]<arr[k-j]){ var tmp=arr[k]; arr[k]=arr[k-j]; arr[k-j]=tmp; console.log(arr); }else{ break; } } } } } console.log(shell_sort([12,9,38,44,98,7,35,59,49,88,38]));
引用传递
var a = [1,2,3];
function add(arr){
arr[0]++;
}
add(a);
console.log(a); // [2,2,3]
伪数组如何转换为数组? (http://www.cnblogs.com/NTWang/p/6280447.html)
伪数组举例:
var list = document.getElementsByTagName("p"); var test = function(){ console.log(argument); // arguments就是伪数组 }
将伪数组转化为数组对象:
方法一、
方法四、ES6中数组的新方法 Array.from()
var list = document.getElementsByTagName("p"); function toArray(list){ //遍历伪数组,返回新数组 var newList = []; for (var i = 0; i < list.length; i++) { newList.push(list[i]); } return newList; } console.log(toArray(list));
方法二、使用数组的slice()方法,使用call或者apply指向伪数组
var list = document.getElementsByTagName("p"); var newList = Array.prototype.slice.call(list); console.log(newList);
ps:slice函数 从某个已有的数组返回选定的元素 http://www.w3school.com.cn/jsref/jsref_slice_array.asp
Array.prototype.slice = function(start,end){//模拟实现slice var result = []; var start = start || 0; //this指向调用的对象,可使用call或apply重定向 var end = end || this.length; for(var i=0; i < end; i++){ result.push(this[i]); } return result; }
方法三、原型继承
var list = document.getElementsByTagName("p"); list.__proto__ = Array.prototype; console.log(list instanceof Array);
var list = document.getElementsByTagName("p"); console.log(Array.from(list) instanceof Array);
call方法
在JS里面,所有的函数,都属于对象
arr.slice();
function test(){
}
window.test();
既可以
对象.函数名()
也可以
函数.调用(对象); //JAVA反射机制
举例:
window.test();
test.call(window);
var arr = { };
arr.test(); // 错误!!!
test.call(arr); //正确!
等价于
arr.test();
list.slice(); //错误!
var newlist = [].slice.call(list); //等价于 list.slice()
数组去重
1. ES6 方法,扩展运算符和 Set 结构相结合
let arr = [3, 5, 2, 2, 5, 5]; let unique = [...new Set(arr)]; // [3, 5, 2] function dedupe(array) { return Array.from(new Set(array)); } dedupe([1, 1, 2, 3]); // [1, 2, 3]
2.在Array对象原型上扩充一个方法unique,实现数组去重
Array.prototype.unique = function(){
var result = [],hash = {};
this.forEach(function(v){
var type = typeof(v); //获取元素类型
hash[v] || (hash[v] = new Array());
if(hash[v].indexOf(type) < 0){
hash[v].push(type); //存储类型
result.push(v);
}
});
return result;
}