Parse Nested Level Json In javascript - javascript

Sample Input:
[
{
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": "special"
},
{
"id": "p2",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p3"},
{"key": "0", "value": "p4"},
{"key": "2", "value": "p5"}
],
"Next": "",
"RepeatText": "p8",
"RepeatTextNew": "p9",
},
{
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
},
{
"id": "p4",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p6"},
{"key": "0", "value": "p7"}
]
},
{
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
},
{
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
},
{
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
},
{
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
},
{
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
]
Sample Output:
{
"test1": {
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": {
"special": {
"id": "p2",
"Key": "special",
"Next": "",
"RepeatText": {
"p8": {
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
}
},
"RepeatTextNew": {
"p9": {
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
},
"specialkey": [
{
"key": "1",
"value": {
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p4",
"Key": "special",
"specialkey": [
{
"key": "1",
"value": {
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
}
}
]
}
},
{
"key": "2",
"value": {
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
}
}
]
}
}
}
}
When the key is equal to special it can have a nested structure and for either we just need to match with the next key
With the below code, I am not able to achieve the expected output.
const processObject = ({ Next, ...rest }) => {
const result = { ...rest };
if (formatData.find((y) => y.Key == 'special')) {
const nextObject = formatData.find((y) => y.Key == 'special')
if (nextObject.specialkey) {
for (let i = 0; i < nextObject.specialkey.length; i++) {
let currentObject = formatData.find((y) => y.id === nextObject.specialkey[i].value)
nextObject.specialkey[i].value = currentObject
}
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
}
if (Next) {
const nextObject = formatData.find((y) => y.id === Next);
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
return result;
};
const response = {
[formatData[0].Key]: processObject(formatData[0]),
};
return response

Is this what you're after?
const input = [
{
"id": "p1", "top": 130, "left" :298, "Key": "test1",
// I've changed this from "special" to "p2"
"Next": "p2"
// rest of input is the same...
},{"id":"p2","Key":"special","specialkey":[{"key":"1","value":"p3"},{"key":"0","value":"p4"},{"key":"2","value":"p5"}],"Next":"","RepeatText": "p8","RepeatTextNew":"p9"},{"id":"p3","user":"aa","Key":"test3","Text":"hi"},{"id":"p4","Key":"special","specialkey":[{"key":"1","value":"p6"},{"key":"0","value":"p7"}]},{"id":"p5","user":"aa","Key":"test5","Text":"hi"},{"id":"p6","user":"aa","Key":"test6","Text":"hi"},{"id":"p7","user":"aa","Key":"test7","Text":"hi"},{"id":"p8","user":"aa","Key":"test8","Text":"hi"},{"id":"p9","user":"aa","Key":"test9","Text": "hi"}];
// Gets an object by its id
const getById = id => input.find(x => x.id === id);
const processObject = ({ Next, specialkey, RepeatText, RepeatTextNew, ...rest }) => {
let processedNext;
if (Next) {
const nextObject = getById(Next);
processedNext = { [nextObject.Key]: processObject(nextObject) };
}
return {
...rest,
// This spread syntax means we don't add the Next or
// specialkey property if it isn't present in the input
// object
...processedNext ? { Next: processedNext } : {},
...RepeatText
? { RepeatText: { [RepeatText]: processObject(getById(RepeatText)) } }
: {},
...RepeatTextNew
? { RepeatTextNew: { [RepeatTextNew]: processObject(getById(RepeatTextNew)) } }
: {},
...specialkey
? {
specialkey: specialkey.map(({ key, value }) => ({
key,
value: processObject(getById(value))
}))
}
: {}
};
}
console.log(processObject(input[0]));
In your code, you seem to be looking up objects by their id, so that's why I changed the first object input's Next from "special" (the Key of the p2 object) to "p2".

Related

filtering an array based on another array based on the order

I have two arrays one is selectedOption and another is defaultOption, if the selectedOption id is present in any of the defaultOption array option property then it will be replaced with the current one . For an example i have added the expected_output
How could i achieve the expected output
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
What I have tried so far
let expected_output = []
selectedOption.forEach(current => {
isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === current.id))
if(isDefaultOptionMatched?.options){
let allMatches = selectedOption.filter(selOpt => {
defaultOption.some(defOption => defOption.options.find(dop => dop.value === selOpt.id))
})
expected_output.push(allMatches[allMatches.length - 1])
}else{
expected_output.push(current)
}
})
What I am getting is 6 elements instead of 5, and its not right.
expected output what I am looking
Instead of 6 objects of expected_output array it will be 5 objects because the second last object id => 6 is part of defaultOption[1].options. The element which got removed is.
{
"count": 3,
"id": "4",
},
Which is part of defaultOption[1].options
expected_output = [
{
"count": 12,
"id": "16",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
Any help is appreciated
Here's a semi-hacky approach (I don't like bucketing the items and remembering the order to rebuild the array later) but it works
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
];
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
];
const result =
selectedOption.reduce((acc, el, order) => {
// bucket each element based on where it's found in defaultOption
const def = defaultOption.find(el2 => el2.options.some(el3 => el3.value === el.id));
if (def) {
const defId = def.item_select.value;
acc[defId] = {...el, order};
} else {
acc[el.id] = {...el, order};
}
return acc;
}, {});
// fix the order and remove the order field
const finish = Object.values(result).sort((a, b) => a.order - b.order).map(({order, ...rest}) => rest);
console.log(finish);
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
let expected_output = []
defaultOption.forEach(defOption => {
let allMatches = selectedOption.filter(selOpt => defOption.options.find(dop => dop.value === selOpt.id))
if(allMatches.length > 0){
expected_output.push(allMatches[allMatches.length - 1])
}
})
selectedOption.forEach(selOpt => {
let isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === selOpt.id))
if(!isDefaultOptionMatched){
expected_output.push(selOpt)
}
})
console.log(expected_output)

Get all parents ids from id list in nested object in javascript

So I have an array of objects which have all nested children property. It is in front-end a treeview, which should expand the nodes until selected ones, for each id in a list. To be able to do this, I have to get all the parents ids for each selected id from the list.
For example, my list of checkedKeys ids:
[16787217, 16787245, 16787266, 16787270, 16787272, 16787265, 16787264]
All the checked items represents the ids from the list object:
My object list looks like this:
[
{
"id": 11,
"name": "Forecast source",
"value": null,
"children": []
},
{
"id": 2,
"name": "Item Type",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item#Cust",
"value": null,
"children": [
{
"id": 16787230,
"name": "Customer",
"value": null,
"children": [
{
"id": 16787291,
"name": "Commercial Network",
"value": null,
"children": []
},
{
"id": 16787296,
"name": "Distribution Site",
"value": null,
"children": []
},
{
"id": 16787265,
"name": "Site",
"value": null,
"children": []
}
]
},
{
"id": 16787254,
"name": "Item",
"value": null,
"children": [
{
"id": 16787294,
"name": "ABC (Regular)",
"value": null,
"children": []
},
{
"id": 16787273,
"name": "ABC (U)",
"value": null,
"children": []
},
{
"id": 16787278,
"name": "ABC (€)",
"value": null,
"children": []
},
{
"id": 16787290,
"name": "Class",
"value": null,
"children": []
},
{
"id": 16787260,
"name": "Family",
"value": null,
"children": [
{
"id": 16787264,
"name": "Product line",
"value": null,
"children": []
}
]
},
{
"id": 16787263,
"name": "Flavour",
"value": null,
"children": []
},
{
"id": 16787262,
"name": "Format",
"value": null,
"children": []
},
{
"id": 16787261,
"name": "Group 1",
"value": null,
"children": []
},
{
"id": 16787292,
"name": "ProdGroup",
"value": null,
"children": []
},
{
"id": 16787293,
"name": "Recipe",
"value": null,
"children": []
},
{
"id": 16787288,
"name": "Sale status",
"value": null,
"children": []
}
]
},
{
"id": 16787245,
"name": "Item#Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family#Warehouse",
"value": null,
"children": []
}
]
}
]
},
{
"id": 3,
"name": "Lead Time",
"value": null,
"children": []
},
{
"id": 5,
"name": "Levels",
"value": null,
"children": []
},
{
"id": 16787268,
"name": "N1",
"value": null,
"children": [
{
"id": 16787269,
"name": "N2",
"value": null,
"children": [
{
"id": 16787270,
"name": "N3",
"value": null,
"children": [
{
"id": 16787271,
"name": "N4",
"value": null,
"children": [
{
"id": 16787272,
"name": "N5",
"value": null,
"children": [
{
"id": 33564497,
"name": "N6",
"value": null,
"children": [
{
"id": 33564498,
"name": "N7",
"value": null,
"children": [
{
"id": 33564499,
"name": "N8",
"value": null,
"children": [
{
"id": 33564500,
"name": "N9",
"value": null,
"children": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
},
{
"id": 16787286,
"name": "Op set",
"value": null,
"children": []
}
]
So my problem is that I can't figure out how to get all parents nodes ids recursively until the root level and push them into the expandedKeys array.
I tried to implement a function like this:
this.list.forEach(el => {
this.setExpandedNodes(el);
});
setExpandedNodes(node: PropertyNode) {
if (node.children) {
node.children.forEach(chld => {
this.checkedKeys.forEach(key => {
if (chld.id === key) {
this.expandedKeys.push(node.id);
} else if (chld.children) {
chld.children.forEach(grChld => {
this.setExpandedNodes(grChld);
});
}
});
});
}
}
But I can't figure out how to get all parent ids starting from each selected id until the root level. Anyone have an idea?
Thanks to this answer I managed to do it.
getPath(model, id) {
let path,
item = model.id ;
if (!model || typeof model !== 'object') {
return;
}
if (model.id === id) {
return [item];
}
(model.children || []).some(child => (path = this.getPath(child, id)));
return path && [item, ...path];
}
setExpandedKeys() {
if (this.checkedKeys && this.checkedKeys.length > 0) {
this.checkedKeys.forEach(k => {
this.list.forEach(
mt => {
const result = this.getPath(mt, k);
if (result) {
this.expandedKeys.push(...result);
}
}
);
});
}
}
this.setExpandedKeys();
I have now all the parents ids until the root.
A function that returns an array of parent objects may look like this:
Using tree-model-js:
const getParentsById = (id, data) => {
var TreeModel = require('tree-model')
const tree = new TreeModel()
let path
for (let item of data) {
const root = tree.parse(item)
root.walk(function (node) {
// Halt the traversal by returning false
if (node.model.id === id) {
path = node.getPath()
return false;
}
});
}
path.pop()
return path.map(item => item.model)
}
Without using tree-model-js:
const getParentsById = (id, data) => {
const isFoundChild = (id, data, parents) => {
if (data.find(item => item.id == id)) {
return true;
}
else {
for (let item of data) {
if (item.children.length)
if (isFoundChild(id, item.children)) {
parents.push(item);
return true;
}
}
return false;
}
}
const parents = [];
if (data.find(item => item.id == id))
return [];
else {
for (let item of data) {
if (item.children.length)
if (isFoundChild(id, item.children, parents)) {
parents.push(item);
return parents;
}
}
}
}
Next, it is enough to apply map() to the result:
let parentsId = getParentsById(16787296, data).map(item => item.id)

Reduce it array to an easier way to map

I'm developing an application and have added new items to my array: type and description.
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
I previously did this to reduce it down to an easier way to map it:
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"]
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
To show the data before I did
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I need to add the description element and type.name to the above. For example for description:
description: e["description"]
To display the elements as in the table:
ITEM
DESCRIPTION
TYPE
202001
202002
I1
item1
type1
100
200
I2
item3
type2
-
300
How do I add and show?
EDIT: console.log(items_dicc[item])
{202001: 100, 202002: 200, description: "item1", type: "type1"}
202001: 100
202002: 200
description: "item1"
type: "type1"
__proto__: Object
{202002: 300, description: "item3", type: "type2"}
202002: 300
description: "item3"
type: "type2"
__proto__: Object
You can add the description and type attribute inside the reduce method like this,
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"],
'description': e['description'],
'type': e.type?.name,
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
console.log(items);
To add the for description and name in the table,
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
<td>{items_dicc[item]?.description}</td>
<td>{items_dicc[item]?.type}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I have been seeing your question regarding these type of tables from yesterday. You have posted several questions with similar things. I suggest you to read some article and understand how JS array methods works instead of asking incremental questions in SO.
Asking in SO might solve your problems for now, but in the long run you will suffer as you don't seem to have a grip on how these things works.
you can simplify your solution like this.
const array = [{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
}
]
const result = array.map(item => {
return Object.keys(item).reduce((a, c) => {
if (c === "date") {
a[item[c].name] = item.price;
} else if (c !== "price" && c !== "id") {
a[c] = (typeof item[c] === "object") ? item[c].name : item[c];
}
return a;
}, {})
});
console.log(result);

Using undescore.js, i'm trying to format the given input to an expected output

Input:
[{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}]
Expected Output:
{
"levels":3,
"level_1_name":"Size",
"level_2_name":"Color",
"level_3_name":"Pattern",
"data":[
{
"value":"Size1",
"data":[
{
"value":"Color1",
"data":[
{
"value":"1"
}
]
}, {
"value":"Color2",
"data":[
{
"value":"4"
}
]
}
]
}, {
"value":"Size2",
"data":[
{
"value":"Color1",
"data":[
{
"value":"3"
}
]
},
{
"value":"Color2",
"data":[
{
"value":"2"
}
]
}
]
}
]
}
I've tried something like that
for(index=0; index<data[0].dimensions.length - 1; index++) {
let temp = _(data).groupBy(function(o) {
return o.dimensions[index].value
})
let keys = Object.keys(temp)
addData(final, keys, temp)
}
obj["data"] = final
function addData(data, keys, temp) {
if (data && data.length) {
return data.forEach(function(data1){
console.log(data1)
return addData(data1, keys, temp)
})
} else {
let data_arr = []
if (Array.isArray(data)) {
keys.forEach(function(key) {
data.push({
value: key,
data: temp[key]
})
})
} else {
keys.forEach(function(key) {
let data_obj = {}
data_obj['value'] = key
data_obj['data'] = temp[key]
data_arr.push(data_obj)
})
data["data"] = data_arr
}
}
}
I've tried the logic to format as per the expected output. It works with level 2 input set, But the logic written doesn't work for level 3 input data set.
Also It would be helpful if you can suggest any algorithms to sort this problem out.
Thanks in advance!
Here is a fairly compact solution using reduce(). (I've edited the input to match your expected output.)
const source = [{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "4"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}];
const output = source.reduce((acc, {dimensions: dims}) => {
const levels = dims.length;
// initialize top-level keys based on first object
if (!acc.hasOwnProperty('levels')) {
acc.levels = levels;
dims.forEach((level, i) => acc[`level_${i+1}_name`] = level.name);
acc.data = [];
}
// iterate over dimension objects and merge with accumulator
let parent = acc.data;
dims.forEach((o, i) => {
let lvlObj = parent.find(e => e.value === o.value);
if (!lvlObj) {
lvlObj = i < levels - 1 ?
{value: o.value, data: []} :
{value: o.value};
parent.push({...lvlObj});
}
parent = lvlObj.data;
});
return acc;
}, {});
console.log(output);

sorting the array of objects keys from another array

How can i merge the array of objects based on the key
let data = [
{
"fields": [
{
"key": "terminal",
"value": null
},
{
"key": "status",
"value": "Enabled"
},
{
"key": "area",
"value": null
},
{
"key": "note",
"value": "Some key notes"
},
{
"key": "group",
"value": "Medium"
},
{
"key": "level",
"value": null
}
],
"name": "test 1",
"number": "123456127890",
"id": "yqweyqweu213"
},
{
"fields": [
{
"key": "terminal",
"value": null
},
{
"key": "status",
"value": "Disabled"
},
{
"key": "area",
"value": "Delhi"
},
{
"key": "note",
"value": "Some key orginal notes"
},
{
"key": "group",
"value": "Medium"
},
{
"key": "level",
"value": "High"
}
],
"name": "test 2",
"number": "173276123612",
"id": "uqweyewueyyuqwe"
},
{
"fields": [
{
"key": "terminal",
"value": 1
},
{
"key": "status",
"value": "Enabled"
},
{
"key": "area",
"value": "Mumbai"
},
{
"key": "note",
"value": "Some key orginal sample notes"
},
{
"key": "group",
"value": "Low"
},
{
"key": "level",
"value": null
}
],
"name": "test 3",
"number": "128737812381723",
"id": "kasjdashdkaskjd"
}
]
const orderArr = [
"area",
"terminal",
"note",
"status",
"group",
"level"
]
Tried with the below snippet
data.forEach(o => {
let keys = []
o.fields.forEach(f => {
keys.push(f.key)
})
let sortedKeys = keys.sort(function(a, b) {
return orderOfFields.indexOf(a) - orderOfFields.indexOf(b);
})
let obj = {}
sortedKeys.forEach(s => {
obj[s] = // how to get the value
})
return obj
})
expectedResult is
let expectedData = [
{
"fields": [
{
"key": "area",
"value": null
},
{
"key": "terminal",
"value": null
},
{
"key": "note",
"value": "Some key notes"
},
{
"key": "status",
"value": "Enabled"
},
{
"key": "group",
"value": "Medium"
},
{
"key": "level",
"value": null
}
],
"name": "test 1",
"number": "123456127890",
"id": "yqweyqweu213"
},
{
"fields": [
{
"key": "area",
"value": "Delhi"
},
{
"key": "terminal",
"value": null
},
{
"key": "note",
"value": "Some key orginal notes"
},
{
"key": "status",
"value": "Disabled"
},
{
"key": "group",
"value": "Medium"
},
{
"key": "level",
"value": "High"
}
],
"name": "test 2",
"number": "173276123612",
"id": "uqweyewueyyuqwe"
},
{
"fields": [
{
"key": "area",
"value": "Mumbai"
},
{
"key": "terminal",
"value": 1
},
{
"key": "note",
"value": "Some key orginal sample notes"
},
{
"key": "status",
"value": "Enabled"
},
{
"key": "group",
"value": "Low"
},
{
"key": "level",
"value": null
}
],
"name": "test 3",
"number": "128737812381723",
"id": "kasjdashdkaskjd"
}
]
You don't have to get sortedKeys and then create an object. You could directly use indexOf inside sort's compareFunction. If a.key has a lower index in orderArrcomapred b.key, the subtraction will return -1 and a will be placed ahead of b.
const data=[{"fields":[{"key":"terminal","value":null},{"key":"status","value":"Enabled"},{"key":"area","value":null},{"key":"note","value":"Some key notes"},{"key":"group","value":"Medium"},{"key":"level","value":null}],"name":"test 1","number":"123456127890","id":"yqweyqweu213"},{"fields":[{"key":"terminal","value":null},{"key":"status","value":"Disabled"},{"key":"area","value":"Delhi"},{"key":"note","value":"Some key orginal notes"},{"key":"group","value":"Medium"},{"key":"level","value":"High"}],"name":"test 2","number":"173276123612","id":"uqweyewueyyuqwe"},{"fields":[{"key":"terminal","value":1},{"key":"status","value":"Enabled"},{"key":"area","value":"Mumbai"},{"key":"note","value":"Some key orginal sample notes"},{"key":"group","value":"Low"},{"key":"level","value":null}],"name":"test 3","number":"128737812381723","id":"kasjdashdkaskjd"}]
const orderArr=["area","terminal","note","status","group","level"]
data.forEach(o =>
o.fields.sort((a, b) => orderArr.indexOf(a.key) - orderArr.indexOf(b.key))
)
console.log(data)
If you want a new array without mutating the original arary, you could use map like this:
const data=[{"fields":[{"key":"terminal","value":null},{"key":"status","value":"Enabled"},{"key":"area","value":null},{"key":"note","value":"Some key notes"},{"key":"group","value":"Medium"},{"key":"level","value":null}],"name":"test 1","number":"123456127890","id":"yqweyqweu213"},{"fields":[{"key":"terminal","value":null},{"key":"status","value":"Disabled"},{"key":"area","value":"Delhi"},{"key":"note","value":"Some key orginal notes"},{"key":"group","value":"Medium"},{"key":"level","value":"High"}],"name":"test 2","number":"173276123612","id":"uqweyewueyyuqwe"},{"fields":[{"key":"terminal","value":1},{"key":"status","value":"Enabled"},{"key":"area","value":"Mumbai"},{"key":"note","value":"Some key orginal sample notes"},{"key":"group","value":"Low"},{"key":"level","value":null}],"name":"test 3","number":"128737812381723","id":"kasjdashdkaskjd"}]
const orderArr=["area","terminal","note","status","group","level"]
const output = data.map(o => ({
...o,
fields: [...o.fields].sort((a, b) => orderArr.indexOf(a.key) - orderArr.indexOf(b.key))
}))
console.log(output)

Categories