数组降维
es6函数
const flatten = x => x.flat(Infinity);
var array = [1, 2, [3, 2], 3, [2, 4, 5, 2, [3, 4, 5]], 4, 5, 6, 7];
console.log(flatten(array));
使用reducer递归遍历
// es6 结构
const flatten = x => x.reduce((pre, cur) => Array.isArray(cur) ? [...pre, ...flatten(cur)] : [...pre, cur], []);
//es5 concat
const flatten = x => x.reduce((pre, cur) => Array.isArray(cur) ? pre.concat(flatten(cur)) : pre.concat(cur), []);
数组字符串化
// 缺点由于字符串化,结果数组的类型会变成字符串
const flatten = x => x.join(',').split(',')
递归+push
const flatten = x => {
let ret = [];
let toArr = (x) => {
x.forEach((item) => {
Array.isArray(item) ? toArr(item) : ret.push(item)
})
};
toArr(x);
return ret
};
数组去重
- Set:使用类型转换先将数组转换为set,然后再将set转为数组。
- 无法对
{}
和[]
去重
- 无法对
- 排序比较相邻元素:利用sort(),然后比较相邻元素是否相等
- 遍历+ 判断(下面的任意组合)
- 外层遍历可以使用下面的方法。
- 判断遍历的当前元素是否已存在
- 借助API直接判断数组内是否存在某个元素
- 借助Map、Object,然后判断是否已存在
- Object属性:Object的key是字符串,为其添加属性的时候会调用其toString方法
- 无法处理引用类型数据。因为会将其转为字符串。
- 无法处理特殊字符串,(”1”,”NaN”,”true”,”null”,”undefined”)
- Map:对于引用类型会比较引用地址。
- Object属性:Object的key是字符串,为其添加属性的时候会调用其toString方法
- 遍历数组+自定义比较逻辑
- 对于一般的数据类型(不涉及到引用类型的)直接用遍历+includes判断,或者借助于es6的Set。
- 对于不含有NaN的一般的数据类型,也可以使用 遍历 + indexOf的方法判断。
- 如果涉及到引用类型的去重,使用遍历+手动写比较函数来处理。
注意点
**
- 注意去重是否要保持原数组不改动。
- 注意NaN以及SymBol类型
具体实现
Set
const arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
function unique (arr) {
return Array.from(new Set(arr))
}
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
reduce+includes
const arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
function unique(arr) {
return arr.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);
}
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
reduce+indexOf
const arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
function unique(arr) {
return arr.reduce((prev, cur) => prev.indexOf(cur) !== -1 ? prev : [...prev, cur], []);
}
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]
filter+indexOf
const arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
实现数组的随机排序
// (1)使用数组 sort 方法对数组元素随机排序,让 Math.random() 出来的数与 0.5 比较,如果大于就返回 1 交换位置,如果小于就返回 -1,不交换位置。
function randomSort(a, b) {
return Math.random() > 0.5 ? -1 : 1;
}
// 缺点:每个元素被派到新数组的位置不是随机的,原因是 sort() 方法是依次比较的。
// (2)随机从原数组抽取一个元素,加入到新数组
function randomSort(arr) {
var result = [];
while (arr.length > 0) {
var randomIndex = Math.floor(Math.random() * arr.length);
result.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return result;
}
// (3)随机交换数组内的元素(洗牌算法类似)
function randomSort(arr) {
var index,
randomIndex,
temp,
len = arr.length;
for (index = 0; index < len; index++) {
randomIndex = Math.floor(Math.random() * (len - index)) + index;
temp = arr[index];
arr[index] = arr[randomIndex];
arr[randomIndex] = temp;
}
return arr;
}
// es6
function randomSort(array) {
let length = array.length;
if (!Array.isArray(array) || length <= 1) return;
for (let index = 0; index < length - 1; index++) {
let randomIndex = Math.floor(Math.random() * (length - index)) + index;
[array[index], array[randomIndex]] = [array[randomIndex], array[index]];
}
return array;
}
详细资料可以参考: 《Fisher and Yates 的原始版》 《javascript 实现数组随机排序?》 《JavaScript 学习笔记:数组随机排序》