数组去重及数组的一些方法

182 阅读3分钟

数组去重

双循环去重

双重for(或while)循环是比较笨拙的方法,它实现的原理很简单:先定义一个包含原始数组第一个元素的数组,然后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对,如果不重复则添加到新数组中,最后返回新数组;因为它的时间复杂度是O(n^2),如果数组长度很大,那么将会非常耗费内存

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    let res = [arr[0]]
    for (let i = 1; i < arr.length; i++) {
        let flag = true
        for (let j = 0; j < res.length; j++) {
            if (arr[i] === res[j]) {
                flag = false;
                break
            }
        }
        if (flag) {
            res.push(arr[i])
        }
    }
    return res
}

indexOf方法去重1

数组的indexOf()方法可返回某个指定的元素在数组中首次出现的位置。该方法首先定义一个空数组res,然后调用indexOf方法对原来的数组进行遍历判断,如果元素不在res中,则将其push进res中,最后将res返回即可获得去重的数组

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (res.indexOf(arr[i]) === -1) {
            res.push(arr[i])
        }
    }
    return res
}


indexOf方法去重2

利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return Array.prototype.filter.call(arr, function(item, index){
        return arr.indexOf(item) === index;
    });
}

相邻元素去重

这种方法首先调用了数组的排序方法sort(),然后根据排序后的结果进行遍历及相邻元素比对,如果相等则跳过改元素,直到遍历结束

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    arr = arr.sort()
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            res.push(arr[i])
        }
    }
    return res
}

利用对象属性去重

创建空对象,遍历数组,将数组中的值设为对象的属性,并给该属性赋初始值1,每出现一次,对应的属性值增加1,这样,属性值对应的就是该元素出现的次数了

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    let res = [],
        obj = {}
    for (let i = 0; i < arr.length; i++) {
        if (!obj[arr[i]]) {
            res.push(arr[i])
            obj[arr[i]] = 1
        } else {
            obj[arr[i]]++
        }
    }
    return res
}

set与解构赋值去重

ES6中新增了数据类型set,set的一个最大的特点就是数据不重复。Set函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return [...new Set(arr)]
}

Array.from与set去重

Array.from方法可以将Set结构转换为数组结果,而我们知道set结果是不重复的数据集,因此能够达到去重的目的

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return Array.from(new Set(arr))
}

join & split

const colors = 'green, red, black';
const colorsArr = colors.split(',');
console.log(colorsArr); // [ 'green', ' red', ' black' ]
const colorsStr = colorsArr.join(',');
console.log(colorsStr); // green, red, black
复制代码

push & pop

const colors = [];
colors.push('green', 'red');
console.log(colors); // ['green', 'red']

const item = colors.pop();
console.log(item); // 'red'
console.log(colors); // ['green']
复制代码

shift & unshift

const colors = ['green', 'red'];
const item = colors.shift();
console.log(item); // 'green'
console.log(colors); // ['red']

colors.unshift('blue', 'grey');
console.log(colors); // ['blue', 'grey', 'red']
复制代码

reverse & sort

const values = [1, 3, 44, 43, 654, 0];
values.reverse();
console.log(values); // [ 0, 654, 43, 44, 3, 1 ]

values.sort();
console.log(values); // [ 0, 1, 3, 43, 44, 654 ] 首字母开始比较
values.sort((val1, val2) => val2 - val1);
console.log(values); // [ 654, 44, 43, 3, 1, 0 ]
复制代码

concat, slice & splice

const colors = ['red', 'green', 'blue'];
const colors2 = colors.concat('yellow', ['black']);
console.log(colors2); // [ 'red', 'green', 'blue', 'yellow', 'black' ]

const colors3 = colors2.slice(1, 5);
console.log(colors3); // [ 'green', 'blue', 'yellow', 'black' ]
console.log(colors2); // [ 'red', 'green', 'blue', 'yellow', 'black' ]

const remove1 = colors2.splice(0, 1);
console.log(remove1); // [ 'red' ]
console.log(colors2); // [ 'green', 'blue', 'yellow', 'black' ]
const remove2 = colors2.splice(1, 0, 'red', 'pink');
console.log(remove2); // [ ]
console.log(colors2); // [ 'green', 'red', 'pink', 'blue', 'yellow', 'black' ]
复制代码

indexOf & lastIndexOf

const values= [1, 3, 4, 6, 7, 4, 3, 1];
console.log(values.indexOf(4)); // 2
console.log(values.lastIndexOf(4)); // 5
console.log(values.lastIndexOf(4, 4)); // 2
console.log(values.lastIndexOf(4, 5)); // 5
复制代码

every, filter, forEach, map & some

every & some

const values = [1, 3, 4, 6, 7, 4, 3, 1];
const everyResult = values.every((item, index, array) => {
  return item > 2;
});
console.log(everyResult); // false

const someResult = values.some((item, index, array) => {
  return item > 2;
});
console.log(someResult); // true
复制代码

filter

const values = [1, 3, 4, 6, 7, 4, 3, 1];
const filterResult = values.filter((item, index, array) => {
  return item > 2;
});
console.log(filterResult); // [ 3, 4, 6, 7, 4, 3 ]
const obj = [ { num: 3 }, { num: 4 }, { num: 1 },{ num: 5 },{ num: 0 }, { num: 4 }];
const filterObjResult = obj.filter((item, index, array) => {
  return item.num > 2;
});
console.log(filterObjResult); // [ { num: 3 }, { num: 4 }, { num: 5 }, { num: 4 } ]
复制代码

map

const values = [1, 3, 4, 6, 7, 4, 3, 1];
const mapResult = values.map((item, index, array) => {
  return item * 2;
});
console.log(mapResult); // [ 2, 6, 8, 12, 14, 8, 6, 2 ]
const obj = [ { num: 3 }, { num: 4 }, { num: 1 },{ num: 5 },{ num: 0 }, { num: 4 }];
const mapObjResult = obj.map((item, index, array) => {
  return item.num;
});
console.log(mapObjResult); // [ 3, 4, 1, 5, 0, 4 ]
复制代码

forEach

const values = [1, 3, 4, 6, 7, 4, 3, 1];
values.forEach((item, index, array) => {
  array[index] = item * 2;
});
console.log(values); // [ 2, 6, 8, 12, 14, 8, 6, 2 ]
复制代码

reduce & reduceRight

const values = [1, 3, 4, 4, 4, 9];
const sum = values.reduce((prev, cur, index, array) => {
  return prev + cur;
});
console.log(sum); // 25

const sumRight = values.reduceRight((prev, cur, index, array) => {
  return prev + cur;
});
console.log(sumRight); // 25

拓展运算符...

const colors = ['green', 'red', 'pink'];
const colors1 = ['white', 'grey'];
const colors2 = [...colors, ...colors1];
console.log(colors2); // [ 'green', 'red', 'pink', 'white', 'grey' ]
复制代码

Array.from() & Array.of()

const obj = {
  '0': '123',
  '1': '456',
  '2': 'c',
  length: 4
}

const arr = Array.from(obj);
console.log(arr); // [ '123', '456', 'c', undefined ]
const values = [1, 1, 3, 5];
const setValue = new Set(values);
const newArr = Array.from(setValue); // 也可以直接[...new Set(values)]
console.log(newArr); // [ 1, 3, 5 ]
const newArr2 = Array.from(newArr, x => x * 2);
console.log(newArr2); // [ 2, 6, 10 ]

console.log(Array.of(undefined, 1, null)); // [ undefined, 1, null ]
复制代码

copyWithin(target, start = 0, end = this.length)

有效时应 start > end

const arr = [1, 3, 4, 4, 5, 8, 10, 1, 0].copyWithin(0, 3, 4);
console.log(arr); // [ 4, 3, 4, 4, 5, 8, 10, 1, 0 ]
const arr = [1, 3, 4, 4, 5, 8, 10, 1, 0].copyWithin(0, 3, 8);
console.log(arr1); // [ 4, 5, 8, 10, 1, 8, 10, 1, 0 ]
复制代码

fill

const colors = ['green', 'red', 'pink'];
const colors1 = colors.fill('white');
console.log(colors1); // [ 'white', 'white', 'white' ] 
复制代码

find & findIndex

const values = [1, 3, 4, 5, 6, NaN];
const findResult = values.find(num => num > 4 ); // 找不到为undefined
console.log(findResult); // 5
const findIndexResult = values.findIndex(num => num > 4 ); // 找不到为-1
console.log(findIndexResult); // 3
复制代码

entries(), keys() & values()

const colors = ["red", "green", "blue"];
for (const index of colors.keys()) {
  console.log(index); // 0 1 2
}

for (const ele of colors.values()) {
  console.log(ele); // red green blue
}
for (const [index, ele] of colors.entries()) {
  console.log(index, ele);
}
// 0 red
// 1 green
// 2 blue

includes

第二个参数是搜索的起始位置

const values = [1, 3, 4, 5, 6, NaN];
console.log(values.includes(NaN)); // true
console.log(values.includes(4, 3)); // false

flat & flatMap

const values = [1, 2, [3, 4]].flat();
console.log(values); // [1, 2, 3, 4]
const valuesDeep = [1, [2, [3]]];
console.log(valuesDeep.flat(Infinity)); // [1, 2, 3]