30 seconds of code - Array 学习(三)

原始地址:https://github.com/30-seconds...

filterNonUnique

过滤调数组中的非唯一值。

使用 Array.prototype.filter() 过滤掉在原数组中存在相同元素的元素。

// 左右开弓,同一元素因为索引相同最后返回 true 会被过滤掉
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));

// example
filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]

filterNonUniqueBy

使用给定比较器函数过滤掉数组中符合要求的非唯一值。

使用 Array.prototype.every() 校验数组内的元素是否是符合给定函数的唯一值,再使用 Array.prototype.filter() 过滤掉非唯一值的元素,剩下的是唯一存在的符合给定函数的元素。

const filterNonUniqueBy = (arr, fn) =>
    arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));

// own understand
const filterNonUniqueBy = (arr, fn) => {
    return arr.filter((v, i) => {
        // 返回最后 arr.every = false 的元素
        // 即整个数组中都没有匹配到的
        return arr.every((x, j) => {
            // 同索引下为 true ,即当前元素
            const indexBool = i === j;
            // 当前元素匹配成功最后返回 true (true === true)
            // 不同元素最后匹配成功返回 false (false === true)
            // 不同元素最后匹配失败返回 true (false === false)
            return indexBool === fn(v, x, i, j);
        });
    });
};

// example
filterNonUniqueBy(
    [
        { id: 0, value: 'a' },
        { id: 1, value: 'b' },
        { id: 2, value: 'c' },
        { id: 1, value: 'd' },
        { id: 0, value: 'e' }
    ],
    (a, b) => a.id == b.id
); // [ { id: 2, value: 'c' } ]

findLast

从数组的右侧开始循环,找出数组中符合给定函数的第一个元素的值。

使用 Array.prototype.filter() 移除数组中不符合指定函数的元素,返回结果集的最后一个元素。

const findLast = (arr, fn) => arr.filter(fn).pop();

// example
findLast([1, 2, 3, 4], n => n % 2 === 1); // 3

findLastIndex

从数组的右侧开始循环,找出数组中符合给定函数的第一个元素的索引。

使用 Array.prototype.map() 对数组进行处理获取数组的值和索引,对新的到的值和索引使用 Array.prototype.filter() 对数据使用给定函数得到符合要求的数组,最后获取最后一个符合要求的元素的索引。

const findLastIndex = (arr, fn) =>
    arr
        .map((val, i) => [i, val])
        .filter(([i, val]) => fn(val, i, arr))
        .pop()[0];

// own understand
const findLastIndex = (arr, fn) => {
    const arrNew = arr.map((val, i) => [i, val]);
    const arrFilter = arrNew.filter(([i, val]) => fn(val, i, arr));
    return arrFilter.pop()[0];
};

// example
findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3)

flatten

将数组递归成指定深度的数组。

指定了一个默认为 1 的指定深度,使用 Array.prototype.reduce() 对数组进行循环,对数组元素进行校验,对递归深度大于 1 和当前元素为数组的情况,对当前元素进行递归,其他情况下可以直接放入到结果集中。

const flatten = (arr, depth = 1) =>
    arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);

// own understand
const flatten = (arr, depth =  1) => {
    return arr.reduce((acc, val) => {
        if (depth > 1 && Array.isArray(val)) {
            return acc.concat(flatten(val, depth - 1));
        }
        return acc.concat(val);
    }, []);
};

// example
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]

forEachRight

从数组的右侧开始循环,对每一个元素执行一次给定的函数。

使用 Array.prototype.slice(0) 对数组进行一次浅拷贝,再使用 Array.prototype.reverse() 将浅拷贝的数组的顺序倒置,最后使用 Array.prototype.forEach() 对数组进行循环调用给定函数。

const forEachRight = (arr, callback) =>
    arr
        .slice(0)
        .reverse()
        .forEach(callback);

// own understand
const forEachRight = (arr, callback) => {
    const arrNew = arr.slice(0);
    const arrReverse = arrNew.reverse();
    return arrReverse.forEach(callback);
};

// example
forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'

groupBy

基于给定的函数或属性将数组进行分组,分组后的 key 为经过给定函数或属性处理过的结果。

使用 Array.prototype.map() 对数组的元素进行处理得到新的数组,使用 Array.prototype.reduce() 对新数组进行分组提取,但是要将原数组的内容放到结果集内。

const groupBy = (arr, fn) =>
    arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
    }, {});

// own understand
const groupBy = (arr, fn) => {
    const arrNew = arr.map(typeof fn === 'function' ? fn : val => val[fn]);
    return arrNew.reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
    }, {});
};

// example
groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}
groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}

head

返回数组的第一个元素。

const head = arr => arr[0];

// example
head([1, 2, 3]); // 1

indexOfAll

返回数组内给定元素的所有索引,不存在时返回一个空数组。

使用 Array.prototype.reduce() 对数据进行循环,如果当前元素和给定的元素全等,则在结果的数组上加上当前索引。

const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);

// own understand
const indexOfAll = (arr, val) => {
    return arr.reduce((acc, el, i) => {
        if (el === val) {
            return [...acc, i];
        }
        return acc;
    }, []);
}

// example
indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []

initial

返回数组除最后一个元素之外的其他数组,即删除最后一个元素。

使用 Array.prototype.slice(0, -1) 截取数组,相当于删除了最后一个元素。

const initial = arr => arr.slice(0, -1);

// example
initial([1, 2, 3]); // [1,2]

你可能感兴趣的:(javascript)