skip to Main Content

I have a Javascript object as below;

grouped = {
    "field1": [{
        "path": "field1",
        "type": "min",
        "message": "Invalid"
    }, {
        "path": "field1",
        "type": "api-error",
        "message": "Invalid"
    }],
    "field2": [{
        "path": "field2",
        "type": "min",
        "message": "Invalid length"
    }, {
        "path": "field2",
        "type": "api-error",
        "message": "API error"
    }]
}

I want to combine them based on unique "message" value and then run the following code on the result

for (const {path,type,message} of result) {
    setError(path, type, message);
}

So, in the above case,

  1. For "field1", since "Invalid" is common string message, setError should be called on result with message "Invalid",
  2. while for "field2", since the string messages are different, the message string should be concatenated and then passed to setError as "Invalid lengthnInvalid"

Again, the number of fields within "grouped" are dynamic. I have shown here just as an example with 2 fields.

Is there an ES6 way of getting this?

2

Answers


  1. It seems you want one result per key in the outer object. So you could iterate the outer object values (which are arrays) and then take the first object from that array, and combine it with a new message property that is the concatenation of unique messages in that array (using Set):

    const grouped = {
        "field1": [{
            "path": "field1",
            "type": "min",
            "message": "Invalid"
        }, {
            "path": "field1",
            "type": "api-error",
            "message": "Invalid"
        }],
        "field2": [{
            "path": "field2",
            "type": "min",
            "message": "Invalid length"
        }, {
            "path": "field2",
            "type": "api-error",
            "message": "API error"
        }]
    };
    
    for (const arr of Object.values(grouped)) {
        if (!arr.length) continue;
        const obj = {
            ...arr[0],
            message: [...new Set(arr.map(obj => obj.message))].join("n")
        };
        console.log(obj);
    }
    Login or Signup to reply.
  2. If I understand you correctly, you could check if they all have the same message, if so, overwrite the message with a joined version of all of them, then loop over that to cal setError

    const grouped = {"field1": [{"path": "field1", "type": "min", "message": "Invalid"}, {"path": "field1", "type": "api-error", "message": "Invalid"}], "field2": [{"path": "field2", "type": "min", "message": "Invalid length"}, {"path": "field2", "type": "api-error", "message": "API error"}] };
    
    Object.values(grouped).forEach(a => {
        let firstMessage = a[0].message;
        let allHaveSameMessage = a.every(aa => aa.message === firstMessage);
        
        let toSet = (allHaveSameMessage)
            ? a
            : a.map(aa => ({ ...aa, message: a.map(aaa => aaa.message).join('\n') }));
            
        toSet.forEach(({ path,type,message }) => console.log(`setError(${path}, ${type}, ${message});`))
    });

    Gives

    setError(field1, min, Invalid);
    setError(field1, api-error, Invalid);
    setError(field2, min, Invalid lengthnAPI error);
    setError(field2, api-error, Invalid lengthnAPI error);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search