Array类型
判断一个变量时数组还是对象
typeof运算符在判断基本数据类型时会很有用,但是在判断引用数据类型时,却显得很吃力。
- instanceof运算符
function getDataType(o) {
if (o instanceof Array) {
return 'Array';
} else if (o instanceof Object) {
return 'Object';
} else {
return 'param is not object type';
}
}
var a = [1, 2, 3];
console.log(getDataType(a));
- 判断构造函数
//判断变量是数组还是对象
function getDataType(o) {
//获取构造函数
var constructor = o.__proto__.constructor || o.constructor;
if (constructor === Array) {
return 'Array';
} else if (constructor === Object) {
return 'Object';
} else {
return 'param is not object type';
}
}
var a = [1, 2, 3];
console.log(getDataType(a));
- toString函数
借助call()函数,直接调用Object原型上的toString()函数
//判断变量是数组还是对象
function getDataType(o) {
var result = Object.prototype.toString.call(o);
if (result === '[object Array]') {
return 'Array';
} else if (result === '[object Object]') {
return 'Object';
} else {
return 'param is no object type';
}
}
var a = [1, 2, 3];
console.log(getDataType(a));
- Array.isArray()函数
数组增加一个isArray()静态函数,用于判断变量是否为数组。该函数只能判断变量是否为数组,并不能确定是否为对象
console.log(Array.isArray([]));
console.log(Array.isArray(null));
filter()函数过滤满足条件的数据
filter()函数用于过滤出满足条件的数据,返回一个新的数组,不会改变原来的数组。
filter()函数接收一个函数作为其参数,返回值为"true"的元素会被添加至新的数组中,返回值为"false"的元素则不会被添加至新的数组中,最后返回这个新的数组。
- 针对简单类型的数组,找出数组中所有为奇数的数字
var filterFn = function (x) {
return x % 2;
};
var arr = [1, 2, 3, 4, 5, 6, 7, 9, 15, 16];
var result = arr.filter(filterFn);
console.log(result);
- 针对复杂类型的数组,找出所有年龄大于18岁的男生
var arrObj = [{
gender: '男',
age: 20
},
{
gender: '女',
age: 23
},
{
gender: '女',
age: 20
},
{
gender: '男',
age: 17
}];
var filterFn = function (obj) {
return obj.age > 18 && obj.gender === '男';
};
var result = arrObj.filter(filterFn);
console.log(result);
reduce()函数累加器处理数组元素
reduce()函数最主要的作用是接收一个函数作为累加器,将数组中的每一个元素从左至右依次执行累加器,返回最终的处理结果
- 求数组每个元素相加的和
var arr = [1, 2, 3, 4, 5];
var sum = arr.reduce(function (accumulator, currentValue) {
return accumulator + currentValue;
}, 0);
console.log(sum);
- 统计数组中每个元素出现的次数
var countOccurrences = function (arr) {
return arr.reduce(function (accumulator, currentValue) {
accumulator[currentValue] ? accumulator[currentValue]++ : accumulator[currentValue] = 1;
return accumulator;
}, {});
};
console.log(countOccurrences([1, 3, 2, 2, 5, 1]));
- 多维度统计数据
将一组人民币分别换算成美元和欧元的等量值
//首先我们需要一组人民币值
var items = [{ price: 10 },
{ price: 50 },
{ price: 100 }];
//利用reduce()函数单独完成一个汇率的计算
var reducers = {
totallnEuros: function (state, item) {
return state.euros += item.price * 0.1265;
},
totallnDollars: function (state, item) {
return state.dollars += item.price * 0.1487;
}
};
//上面的reducers通过一个manager()函数,利用object.keys()函数同时执行多个函数,每个函数完成各自的汇率计算
var manageReducers = function (reducers) {
return function (state, item) {
return Object.keys(reducers).reduce(
function (nextState, key) {
reducers[key](state, item);
return state;
},
{}
);
}
};
//对上面的一组人民币值Items数组进行运算
var bigTotalPriceReducer = manageReducers(reducers);
var initialState = { euros: 0, dollars: 0 };
var totals = items.reduce(bigTotalPriceReducer, initialState);
console.log(totals);
求数组的最大值和最小值
- 通过prototype属性扩展min()函数和max()函数
Array.prototype.min = function () {
var min = this[0];
var len = this.length;
for (var i = 1; i < len; i++) {
if (this[i] < min) {
min = this[i];
}
}
return min;
};
Array.prototype.max = function () {
var max = this[0];
var len = this.length;
for (var i = 1; i < len; i++) {
if (this[i] > max) {
max = this[i];
}
}
return max;
};
var arr = [2, 56, 34, 1, 89, 99];
console.log(arr.max());
console.log(arr.min());
- 借助Math对象的min()函数和max()函数
通过apply()函数改变函数的执行体,将数组作为参数传递给apply()函数,这样数组就可以直接调用Math()对象的min()函数和max()函数来获取返回值
//最大值
Array.max = function (array) {
return Math.max.apply(Math, array);
};
//最小值
Array.min = function (array) {
return Math.min.apply(Math, array);
};
var arr = [2, 56, 34, 1, 89, 99];
console.log(Array.max(arr));
console.log(Array.min(arr));
</script>
- 算法2的优化(实际运用中推荐)
将算法2中的静态函数优化为支持链式调用
Array.prototype.max = function () {
return Math.max.apply({}, this);
};
Array.prototype.min = function () {
return Math.min.apply({}, this);
};
//max和Min函数属于实例方法。可以直接通过数组调用
var arr = [2, 56, 34, 1, 89, 99];
console.log(arr.max());
console.log(arr.min());
- 借助Array类型的reduce()函数
//最大值
Array.prototype.max = function () {
return this.reduce(function (preValue, curValue) {
return preValue > curValue ? preValue : curValue;
});
};
//最小值
Array.prototype.min = function () {
return this.reduce(function (preValue, curValue) {
return preValue > curValue ? curValue : preValue;
});
};
var arr = [2, 56, 34, 1, 89, 99];
console.log(arr.max());
console.log(arr.min());
- 借助Array类型的sort()函数
借助数组原生的sort()函数对数组进行排序,排序完成后的首尾元素即是数组的最小、最大元素
var sortFn = function (a, b) {
return a - b;
};
var arr = [2, 56, 34, 1, 89, 99];
var sortArr = arr.sort(sortFn);
console.log(sortArr[0]);
console.log(sortArr[sortArr.length - 1]);
- 借助ES6的扩展运算符
var arr = [2, 56, 34, 1, 89, 99];
console.log(Math.min(...arr));
console.log(Math.max(...arr));
数组遍历的7种方法
- 最原始的for循环
var arr = [2, 56, 34, 1, 89, 99];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
- 基于forEach()函数的方法
forEach()函数算是在数组实例方法中用于遍历调用次数最多的函数
var arr = [11, 22, 33];
arr.forEach(function (element, index, array) {
console.log(element);
})
forEach()函数是在ES5中新添加的,它可能不兼容只支持低版本js的浏览器,供一个polyfill来实现(代码参考书籍)
- 基于map()函数的方法
map()函数并不会改变原数组,其接收的参数和forEach()函数一样
map()回调函数中需要通过return返回处理后的值
将一个数组中的每个元素做平方运算,通过map()函数很容易做到
var arr = [1, 2, 3];
var arrayOfSquares = arr.map(function (element) {
return element * element;
});
console.log(arrayOfSquares);
- 基于some()函数与every()函数的方法
function isBigEnough(element, index, array) {
return element > 4;
}
var passed1 = [1, 2, 3, 4].some(isBigEnough);
var passed2 = [1, 2, 3, 4, 5].some(isBigEnough);
console.log(passed1);
console.log(passed2);
var passed3 = [2, 3, 4].every(isBigEnough);
var passed4 = [5, 6].every(isBigEnough);
console.log(passed3);
console.log(passed4);
- 基于find()函数的方法
var value = [1, 5, 10, 15].find(function (element, index, array) {
return element > 9;
});
var value2 = [1, 5, 10, 15].find(function (element, index, array) {
return element > 20;
});
console.log(value);
console.log(value2);
数组去重的7种算法
- 遍历数组
在函数内部新建一个数组,对传入的数组进行遍历。如果遍历的值不在新数组种就添加进去,如果已存在就不做处理
function arrayUnique(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
if (result.indexOf(array[i]) === -1) {
result.push(array[i]);
}
}
return result;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7];
console.log(arrayUnique(array));
- 利用对象键值对
新建一个js对象以及一个新的数组,对传入的数组进行遍历,判断当前遍历的值是否为js对象的键。如果是,表示该元素已经出现过,不做处理;如果不是,表示第一次出现,给该js对象插入该键,同时插入新的数组
function arrayUnique1(array) {
var obj = {},
result = [],
val, type;
for (var i = 0; i < array.length; i++) {
val = array[i];
if (!obj[val]) {
obj[val] = 'yes';
result.push(val);
}
}
return result;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7];
console.log(arrayUnique1(array));
上面的代码存在缺陷,即不能判断Number类型和String类型的数字
function arrayUnique1(array) {
var obj = {},
result = [],
val, type;
for (var i = 0; i < array.length; i++) {
val = array[i];
type = typeof val;
if (!obj[val]) {
obj[val] = [type];
result.push(val);
} else if (obj[val].indexOf(type) < 0) {
//判断数据类型是否存在
obj[val].push(type);
result.push(val);
}
}
return result;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
console.log(arrayUnique1(array));
- 先排序,再去重
先用sort()函数对数组进行排序,然后对排序后的数组进行相邻元素的去重,将去重的后的元素添加至新的数组中
function arrayUnique3(array) {
var result = [array[0]];
array.sort(function (a, b) {
return a - b;
});
for (var i = 0; i < array.length; i++) {
if (array[i] !== result[result.length - 1]) {
result.push(array[i]);
}
}
return result;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
console.log(arrayUnique3(array));
-
优先遍历数组
利用双层循环 -
基于reduce()函数
利用reduce()函数,借助一个key-value对象
function arrayUnique5(array) {
var obj = {}, type;
return array.reduce(function (preValue, curValue) {
type = typeof curValue;
if (!obj[curValue]) {
obj[curValue] = [type];
preValue.push(curValue);
} else if (obj[curValue].indexOf(type) < 0) {
obj[curValue].push(type);
preValue.push(curValue);
}
return preValue;
}, []);
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
console.log(arrayUnique5(array));
- 借助ES6的Set数据结构
Set数据结构,类似于数组,有一个特点,即成员都是唯一的,所以Set具有自动去重的功能
在ES6中,Array类型增加了一个from()函数,用于将类数组对象转化为数组,然后再结合Set可以完美实现数组的去重
function arrayUnique6(array) {
return Array.from(new Set(array));
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
console.log(arrayUnique6(array));
- 借助ES6的Map数据结构
基于key-value存储数据的结构。每个key都只对应唯一的value
基于Map数据结构,通过filter()函数过滤,即可获得去重后的结果
function arrayUnique7(array) {
var map = new Map();
return array.filter((item) => !map.has(item) && map.set(item, 1));
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
console.log(arrayUnique7(array));
找出数组中出现次数最多的元素
- 利用键值对
将数组元素作为对象的键,出现的次数作为值
获取键值对后进行遍历,获取值最大的那个元素
function findMost1(arr) {
if (!arr.length) {
return;
}
if (arr.length === 1) {
return 1;
}
var res = {};
//遍历数组
for (var i = 0; i < arr.length; i++) {
if (!res[arr[i]]) {
res[arr[i]] = 1;
} else {
res[arr[i]]++;
}
}
//遍历res
var keys = Object.keys(res);
var maxNum = 0, maxEle;
for (var i = 0; i < arr.length; i++) {
if (res[keys[i]] > maxNum) {
maxNum = res[keys[i]];
maxEle = arr[i];
}
}
return maxEle + ":" + maxNum;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
console.log(findMost1(array));
object.key()返回的是res键值对里面的键
- 对算法1的优化
将两次遍历优化为一次遍历
function findMost2(arr) {
var h = {};
var maxNum = 0;
var maxEle = null;
for (var i = 0; i < arr.length; i++) {
var a = arr[i];
h[a] === undefined ? h[a] = 1 : h[a]++;
//在当前循环中直接比较出现次数最大值
if (h[a] > maxNum) {
maxEle = a;
maxNum = h[a];
}
}
return maxEle + ":" + maxNum;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
console.log(findMost2(array));
- 借助Array类型的reduce()函数
function findMost3(arr) {
var maxEle;
var maxNum = 1;
var obj = arr.reduce(function (p, k) {
p[k] ? p[k]++ : p[k] = 1;
if (p[k] > maxNum) {
maxEle = k;
maxNum++;
}
return p;
}, {});
return maxEle + ":" + maxNum;
}
var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
console.log(findMost3(array));
- 借助ES6与逗号运算符进行代码优化(暂不理解)