Разделить массив с помощью пользовательской функции - PullRequest
0 голосов
/ 09 октября 2018

Я хотел бы разбить массив на несколько кусков, но применяя к нему функцию, чтобы решить, как создавать куски.

Например, если у меня есть массив букв, цифр или букв и цифр,применить функцию к массиву, чтобы разделить его на массив массивов предыдущих категорий.

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 голосов
/ 18 января 2019

Попробуйте сделать это

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))
0 голосов
/ 09 октября 2018

Подсказка

Ключ к ответу заключается в том, чтобы каким-то образом реорганизовать исходный массив таким образом, чтобы все элементы с одинаковым ключом находились в одном месте.

Самый простой способ решить эту проблему - использовать hash-map.Каждый элемент в hash-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);
0 голосов
/ 09 октября 2018
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));

Я думаю, что это удовлетворяет.

0 голосов
/ 09 октября 2018

Вот способ сделать это через 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 играет роль фильтрации элементов по number, string with 1 length и other.Этот вывод используется myChunkFunction для размещения элемента в правильном массиве.

Вы можете сделать что-то подобное с меньшим контролем и в одну строку с массивом 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, других длинах.

Youможет обернуть это в функцию.

...