How to group by json using reduce?

怎甘沉沦 提交于 2020-01-25 06:12:08

问题


Please take a look at my current json. I want to recursively group by this one.

[{ "mode": "AR", "fname": "ta", "lname": "da", "w_lng": 
             "1.23", "w_lat": "2.23","other":"a"},
           { "mode": "AR", "fname": "ta", "lname": "Dash", "w_lng": 
             "1.23", "w_lat": "2.23","other":"b" },
           { "mode": "AR1", "fname": "ka", "lname": "ja", "w_lng": 
             "3.23", "w_lat": "4.23","other":"c" },
           { "mode": "AR", "fname": "Kiran", "lname": "Dash", "w_lng": 
             "5.23", "w_lat": "6.23","other":"d" },
           { "mode": "AR", "fname": "Milan", "lname": "Dash", "w_lng": 
             "7.23", "w_lat": "8.23","other":"e" },
           { "mode": "AR1", "fname": "ka", "lname": "ja", "w_lng": 
             "8.23", "w_lat": "9.23","other":"f" }]

What I am am looking for:

  {
  "mode": "AR",
  "results": [
    {
    "fname": "ta",
    "lname": "da",
    "w_level": [
                { "w_lng": "1.23",
                  "w_lat": "2.23"
                  "other":[{"other":"a","other":"b"}]
                },
                {"w_lng": "3.xx",
                 "w_lat": "4.xx"
                 "....":[........]
                }
              ]  
   }
   {
    "fname": "ka",
    "lame": "ja",
    "w_level": [
        {
            "w_lng": "6.xx",
            "w_lat": "5.xx"
            .....................
                }
              ]  
   }
 ]
},
{
  "mode": "AR1",
  "results": [
    {
    "fname": "ka",
    "lname": "ja",
    "w_level": [
                { "w_lng": "6.xx",
                  "w_lat": "5.xx"
                  "....":[........]
                }
              ]  
   }

 ]
}

What I have tried:

Object.values(inArr.reduce((item, currItem) => {

var { mode, fname, lname } = currItem;

if (!item[mode]) item[mode] = { mode, results: [] }; 

let w_level = {};
for (let key of Object.keys(currItem)) {
  if (key !== "fname" && key !== 'lname' && key !== 'mode') {
    w_level[key] = currItem[key];
  }
}

item[mode].results.push({fname: fname, lname: lname, w_level: [w_level]});
return item;
}, {}))

But the problem is fname and lname again even it is same. I want to group by recursively. First it will group by mode. Then it will group by fname+lname under this mode. if anything same it will be added like tree.


回答1:


Here is my final solution. The user can specify the key for grouping.

const reduceArrayByKeys = (inArr, keys, restKey) => {
    const reduced = inArr.reduce((prev, cur) => {
        const copied = { ...cur }
        keys.forEach(key => delete copied[key])
        const existing = prev.find(item => keys.every(key => item[key] === cur[key]))
        if (existing) {
            existing[restKey].push(copied)
        } else {
            const newItem = {}
            keys.forEach(key => newItem[key] = cur[key])
            newItem[restKey] = [copied]
            prev.push(newItem)
        }
        return prev
    }, [])

    return reduced
}

We can specify the keys by which we are going to group the array. We can use this reduceArrayByKeys function to group the array as we want. Below is the example code

const reduced = reduceArrayByKeys(inArr, ['mode'], 'results')
reduced.forEach(item => {
    const results = item.results
    item.results = reduceArrayByKeys(results, ['fname', 'lname'], 'w_level')

    item.results.forEach(child => {
        child.w_level = reduceArrayByKeys(child.w_level, ['w_lng', 'w_lat'], 'other')
    })
})

You can call reduceArrayByKeys function for w_level as well.



来源:https://stackoverflow.com/questions/59779931/how-to-group-by-json-using-reduce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!