1

Please take a look at my current json.

[ 
 {"mode": "AR","fname": "ta","lname":"da","w_lng":"2.xx","w_lat":"1.xx"....},
 {"mode": "AR","fname": "ta","lname":"da","w_lng":"3.xx","w_lat": "4.xx"....},
 {"mode": "AR","fname": "ka","lname":"ja","w_lng":"6.xx","w_lat": "5.xx"....}
]

Now What I am looking for:

{
"mode": "AR",
"results": [
        {
        "fname": "ta",
        "lname": "da",
        "w_level": [
                    { "w_lng": "2.xx",
                      "w_lat": "1.xx"
                      "anothelevel":[........]
                    },
                    {"w_lng": "3.xx",
                     "w_lat": "4.xx"
                     "anothelevel":[........]
                    }
                  ]  
       }
       {
        "fname": "ka",
        "lname": "ja",
        "w_level": [
            {
                "w_lng": "x.xx",
                "w_lat": "x.xx"
                .....................
                    }
                  ]  
       }
     ]
  }

It is same as we do in SQL group by. suppose First group by world, then country, then city, then village etc. I was tried through group by. but the result is not my expected output. Please suggest me what should I do.

Suman Kumar Dash
  • 681
  • 5
  • 19
  • JSON cannot have repeated keys, you need to think about restructuring your data. – AZ_ Jan 16 '20 at 07:44
  • @AZ_ actually you can : https://stackoverflow.com/questions/21832701/does-json-syntax-allow-duplicate-keys-in-an-object – Ray Jan 16 '20 at 07:56
  • @Raymond it's interesting to learn that technically you can, but I don't think it would be any use. If you parse the Json to a JavaScript object, it will just use the value of the last key. – Patrick Hund Jan 16 '20 at 08:02
  • 1
    @Raymond, you can have repeated keys when creating a JS Native object but you cannot have in a JSON. Please read through the stack answers you posted and understand the difference between `JSON` and `JS Native object.` – AZ_ Jan 16 '20 at 08:13
  • @Suman, you can use reduce function to group your JSON as per your requirement. Please have a look at my answer below. Hope it solves your issue. – Kiran Dash Jan 16 '20 at 08:19

3 Answers3

1

Solution using reduce:

const inArr = [{"mode":"AR","fname":"Kiran","lname":"Dash","w_lng": "1.23", "w_lat": "2.23"},{"mode":"AR1","fname":"Suman","lname":"Dash","w_lng": "3.23", "w_lat": "4.23"},{"mode":"AR","fname":"Raman","lname":"Dash","w_lng": "5.23", "w_lat": "6.23"},{"mode":"AR","fname":"Milan","lname":"Dash","w_lng": "7.23", "w_lat": "8.23"},{"mode":"AR1","fname":"Naman","lname":"Dash","w_lng": "8.23", "w_lat": "9.23"},{"mode":"AR2","fname":"Phulan","lname":"Dash","w_lng": "10.23", "w_lat": "11.23"}]

console.log(
  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;
  }, {}))
);

Code walk through:

Loop over the input array, and group into an object indexed by mode. Create an object with a result array if the mode doesn't exist yet, and push to that array.

Note: For the sake of simplicity, I have done it to one level. Please use the same approach to create multiple levels if you want.

Kiran Dash
  • 4,816
  • 12
  • 53
  • 84
  • 1
    Same thing I already tried: let parse_groupby = [parseD.reduce((a, c) => (a[c.mode] = (a[c.mode] || []).concat(c), a), {})]; But do not understand multilevel. – Suman Kumar Dash Jan 16 '20 at 09:03
  • 1
    If possible just add more one level. – Suman Kumar Dash Jan 16 '20 at 09:12
  • 1
    @SumanDash You can use the exact same logic to go one level deep. – Kiran Dash Jan 16 '20 at 09:16
  • 1
    where I have to add multilevel ? do not understand how can I define object inside it. – Suman Kumar Dash Jan 16 '20 at 09:49
  • 1
    @SumanDash I have modified the answer to add multilevel JSON as shown in your question. Followed the answer from ramratan. Hope that solves your problem – Kiran Dash Jan 16 '20 at 14:34
  • I have edited my question. Please take a look at. Your answer is not group by recursively. What will be happened when same fname and lastname come again under same mode? – Suman Kumar Dash Jan 17 '20 at 00:50
  • You are welcome. Glad that you found the solution. Since your problem is solved, pls close this post by marking one of the answers as the correct one or posting your solution in the answers and mark it as correct. Cheers! Happy Weekend – Kiran Dash Jan 17 '20 at 07:44
1
objMap = {};
for (let temp of obj) {
  if (!objMap[temp.mode]) {
    objMap[temp.mode] = { mode: temp.mode, results: [] }
  }
  let tempObj = { w_level: [], fname: temp.fname, lname: temp.lname };
  let w_level = {};
  for (let key of Object.keys(temp)) {
    if (key !== "fname" && key !== 'lname' && key !== 'mode') {

      w_level[key] = temp[key];

    }


  }
  tempObj.w_level.push(w_level)
  objMap[temp.mode].results.push(tempObj)
}


NOTE:get object by using Object.values(objMap);
ramratan
  • 11
  • 2
0

------At last I found solution-----------

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
}

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')
  })
})
Suman Kumar Dash
  • 681
  • 5
  • 19