使用自定义函数拆分数组

时间:2018-10-09 17:52:56

标签: javascript arrays algorithm ecmascript-6 split

我想将一个数组拆分为多个块,但对其应用一个函数来决定如何创建块。

例如,如果我有一个字母,数字或字母和数字组成的数组,请对该数组应用一个函数,以将其拆分为先前类别的数组。

let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']
myChunkFunction(arr, myCustomSplitFunction)

// result
[['a','b','c'], ['1','2','3'], ['a1', 'a2','a3']]

Lodash有一个块函数,但它拆分为n个块,数组也有切片函数,但是您需要指定开始和结尾,所以我如何使用自定义函数进行拆分。

4 个答案:

答案 0 :(得分:1)

这是通过ES6执行此操作的一种方法:

let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']

const splitFn = (str) => Number.isInteger(+str) ? 0 : str.length == 1 ? 1 : 2
const myChunkFunction = (arr, fn) => arr.reduce((r,c) => {
   let t = fn(c)
   r[t] = [...r[t], c]
   return r
}, [[],[],[]])

console.log(myChunkFunction(arr, splitFn))

typeFn的作用是将元素过滤到numberstring with 1 lengthothermyChunkFunction使用该输出将元素放置在正确的数组中。

您可以通过较少的控制并用reduce和ES6数组扩展在一行中完成以下操作:

let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']

const result = arr.reduce((r,c) => 
  (Number.isInteger(+c) ? r[0] = [...r[0], c] : 
  c.length == 1 ? r[1] = [...r[1], c] : r[2] = [...r[2], c], r), [[],[],[]])

console.log(result)

[[],[],[]]开始,然后根据数字,字符串的长度== 1,其他长度填充每个子数组。

您可以将其包装在函数中。

答案 1 :(得分:1)

提示

答案的关键是以某种方式重组源数组,以使所有具有相同关键点的元素都位于同一位置。

我想解决这个问题的最简单方法是使用hash-maphash-map中的每个元素都是一个不同的数组,其中包含具有相同键的所有元素。

在继续阅读并查看完整解决方案之前,请自己尝试一下。


实施

如您所见,我尽可能地解决了它。为避免突变,我使用reduce遍历源数组并将每个元素放入哈希图中(通过从元素生成键)。

我反复使用浅拷贝重新创建最终的哈希映射。最后,我使用Object.values

将哈希图转换为数组数组(因为这是您的需求)

const splitArrayByKey = extractKey => array => {
    const arraysByKey_obj = array.reduce((hashMapOfArrays,element)=> {
        const key = extractKey(element);
        
        // if we already added an element with the same key, 
        // then we add the current element to there.
        // else, we create a new key and put the current element there.
        if(hashMapOfArrays.hasOwnProperty(key))
            return {
                ...hashMapOfArrays,
                [key]: [...hashMapOfArrays[key],element]
            };
        return {
            ...hashMapOfArrays,
            [key]: [element]
        };
    },{});

    // transform the arraysByKey_obj to an array of arrays:
    return Object.values(arraysByKey_obj);
};

// example 1:
const result1 = splitArrayByKey(element=>element)([1,2,3,1,2,3]);
console.log(result1);

console.log('------------------');

// example 2:
const result2 = splitArrayByKey(element=>element.id)([{id:1,x:1},{id:{},x:2},{id:"id",x:3},{id:1,x:4}]);
console.log(result2);

答案 2 :(得分:1)

尝试这样做

let arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3']

const splitFn = (str) => Number.isInteger(+str) ? 0 : str.length == 1 ? 1 : 2
const myChunkFunction = (arr, fn) => arr.reduce((r,c) => {
   let t = fn(c)
   r[t] = [...r[t], c]
   return r
}, [[],[],[]])

console.log(myChunkFunction(arr, splitFn))

答案 3 :(得分:0)

const arr = ['a', 'b', '1', '2', 'a1', 'a2', 'c', '3', 'a3'];
const getClassification = function(x){
    const hasNumber = x.split('').some(x => parseFloat(x));
    const hasChar = x.split('').some(x => !parseFloat(x));

    if(!parseFloat(x) && (!hasNumber && hasChar)) return 0;
    else if(parseFloat(x)) return 1;
    else return 2;
}

const myChunkFunction = function(arr, classifier){
    let jaggedArray = [[], [], []];

    arr.forEach(x => {
        jaggedArray[classifier(x)].push(x);
    })

    return jaggedArray;
}

console.log(myChunkFunction(arr, getClassification));

我认为这令人满意。