Search code examples
javascriptarraysmethodsflatmap

How to get accumulator in flatMap array methode in JavaScript(flatmap vs reduce)?


There is an initial array that needs to be mapped and filtered at the same time:

let data = [
        {
            "id": 1,
            "parentId": null,
            "dxId": "1_id",
            "dxParentId": null,
            "defName": "group1"
        },
        {
            "id": 12,
            "parentId": null,
            "dxId": "12_id",
            "dxParentId": null,
            "defName": "группа3"
        },
        {
            "id": 8,
            "parentId": 1,
            "dxId": "1_id/13",
            "dxParentId": "1_id",
            "defName": "group4"
        },
        {
            "id": 5,
            "parentId": 1,
            "dxId": "1_id/20",
            "dxParentId": "1_id",
            "defName": "user1"
        },
        {
            "id": 5,
            "parentId": 1,
            "dxId": "1_id/20",
            "dxParentId": "12_id",
            "defName": "user1"
        },
    ];

I filter by the presence of the parentide property, and collect the resulting array of strings (not the initial array of objects).

originally I did it through reduce methode:

resultArr = data.reduce((filtered, obj) => {
                                if(  obj.dx_parentId !== null) {
                                    if(!(filtered.includes(obj.dxParentId)))  {
                                        filtered.push(obj.dxParentId);
                                    }
                                }
                                return filtered;
                            }, []);
 console.log(resultArr , 'result'); // ['1_id', '12_id'] 'result'

then I discovered for myself that this can be done with the flatMap array method

resultArr =  data.flatMap((obj) =>  obj.dxParentId !== null ? [obj.dxParentId] : []);
console.log(resultArr , 'result'); //['1_id', '1_id', '12_id'] 'result'

If you notice that in the case of reduce I use filtered (accumulating array) I do an additional check using includes and I get the result that I need.

The question is how to do the same it via flatMap? is it possible to access the accumulating result at each iteration?

Additionally: can someone tell me what is better to use to solve this case, in terms of optimization? mb forEach? thanks in advance


Solution

  • You cannot access the array that is being built in flatMap. In mapping, and also mapping-with-flattening, the callback is supposed to return a value that depends only on the particular item.

    You might simple not want to use reduce at all for an imperative algorithm like this:

    const resultArr = [];
    for (const obj of data) {
        if (obj.dxParentId !== null) {
            if (!resultArr.includes(obj.dxParentId)) {
                filtered.push(obj.dxParentId);
            }
        }
    }
    console.log(resultArr, 'result');
    

    However, to get unique values from an array there is a much better (simpler and more efficient) way:

    const resultArr = Array.from(new Set(data.map(obj => obj.dxParentId).filter(id => id !== null)));
    console.log(resultArr, 'result');