Related
I am converting the object to tree node format using the below method
function getNodes(object) {
return Object
.entries(object)
.map(([key, value]) => value && typeof value === 'object' ?
{
value: key + value,
label: key,
children: getNodes(value)
} :
{
value: key + value,
label: key
}
);
}
The sample object is:
var object = {
"income-array": [{
"income": {
"id": "1234",
"currency": "dollar",
"details": {
"individual-income": [{
"name": "abcd",
"income": 100
}, {
"name": "xyz",
"income": 500
}]
}
}
}]
}
I am getting this result:
[{
"value": "income-array[object Object]",
"label": "income-array",
"children": [{
"value": "0[object Object]",
"label": "0",
"children": [{
"value": "income[object Object]",
"label": "income",
"children": [{
"value": "id1234",
"label": "id"
}, {
"value": "currencydollar",
"label": "currency"
}, {
"value": "details[object Object]",
"label": "details",
"children": [{
"value": "individual-income[object Object],[object Object]",
"label": "individual-income",
"children": [{
"value": "0[object Object]",
"label": "0",
"children": [{
"value": "nameabcd",
"label": "name"
}, {
"value": "income100",
"label": "income"
}]
}, {
"value": "1[object Object]",
"label": "1",
"children": [{
"value": "namexyz",
"label": "name"
}, {
"value": "income500",
"label": "income"
}]
}]
}]
}]
}]
}]
}]
I want to get the value property path from root to a particular node like the below. I am confused with how to append step by step path to value.
[{
"value": "income-array",
"label": "income-array",
"children": [{
"value": "['income-array'][0]",
"label": "0",
"children": [{
"value": "['income-array'][0]['income']",
"label": "income",
"children": [{
"value": "['income-array'][0]['income']['id']",
"label": "id"
}, {
"value": "['income-array'][0]['income']['currencydollar']",
"label": "currency"
}, {
"value": "['income-array'][0]['income']['details']",
"label": "details",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income']",
"label": "individual-income",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][0]",
"label": "0",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][0]['name']",
"label": "name"
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][0]['income']",
"label": "income"
}]
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][1]",
"label": "1",
"children": [{
"value": "['income-array'][0]['income']['details']['individual-income'][1]['name']",
"label": "name"
}, {
"value": "['income-array'][0]['income']['details']['individual-income'][1]['income']",
"label": "income"
}]
}]
}]
}]
}]
}]
}]
Can you please guide me how to resolve this? Thanks
The outer function needs to pass its own current absolute path (which is value in your code) to the inner function,
in order to let the inner function know the previous paths.
Notice the parentPath='' parameter and children: getNodes(value, currentPath) below
function getNodes(object, parentPath = "") {
return Object.entries(object).map(([key, value]) => {
const currentPath = parentPath + `[${key}]`;
return value && typeof value === "object"
? {
value: currentPath,
label: key,
children: getNodes(value, currentPath),
}
: {
value: currentPath,
label: key,
};
});
}
After that, run getNodes(object) in the browser and you will get a result like this.
[
{
"value": "[income-array]",
"label": "income-array",
"children": [
{
"value": "[income-array][0]",
"label": "0",
"children": [
{
"value": "[income-array][0][income]",
"label": "income",
"children": [
{
"value": "[income-array][0][income][id]",
"label": "id"
},
{
"value": "[income-array][0][income][currency]",
"label": "currency"
},
{
"value": "[income-array][0][income][details]",
"label": "details",
"children": [
{
"value": "[income-array][0][income][details][individual-income]",
"label": "individual-income",
"children": [
{
"value": "[income-array][0][income][details][individual-income][0]",
"label": "0",
"children": [
{
"value": "[income-array][0][income][details][individual-income][0][name]",
"label": "name"
},
{
"value": "[income-array][0][income][details][individual-income][0][income]",
"label": "income"
}
]
},
{
"value": "[income-array][0][income][details][individual-income][1]",
"label": "1",
"children": [
{
"value": "[income-array][0][income][details][individual-income][1][name]",
"label": "name"
},
{
"value": "[income-array][0][income][details][individual-income][1][income]",
"label": "income"
}
]
}
]
}
]
}
]
}
]
}
]
}
]
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);
how to merge the keys in the array into a single key with using the seperator, if value is null dont take it
let keysToBeMerged = [['note', 'status', seperator: ' ,'], ['group', 'level', seperator: ' ()']];
let data = [
{
"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"
}
]
i have a collection called keysToBeMerged, i need to find the key from the he fields collection and need to merge some keys into a single key with merged values with using the seperator.
tried with below snippet
data.map(o => {
let key = []
let value = []
o.fields.forEach(f => {
keysToBeMerged.forEach(kColl => {
if(kColl.includes(f.key)){
key.push(f.key)
value.push(f.value)
}
})
console.log(key.join(""))
console.log(value.join(""))
})
return o
})
the expectedResult is shown below. Any help appreciated
let expectedResult = [
{
"fields": [
{
"key": "area",
"value": null
},
{
"key": "terminal",
"value": null
},
{
"key": "note|status",
"value": "Some key notes, Enabled"
},
{
"key": "group|level",
"value": "Medium"
}
],
"name": "test 1",
"number": "123456127890",
"id": "yqweyqweu213"
},
{
"fields": [
{
"key": "area",
"value": "Delhi"
},
{
"key": "terminal",
"value": null
},
{
"key": "note|status",
"value": "Some key orginal notes, Disabled"
},
{
"key": "group|level",
"value": "Medium (High)"
},
],
"name": "test 2",
"number": "173276123612",
"id": "uqweyewueyyuqwe"
},
{
"fields": [
{
"key": "area",
"value": "Mumbai"
},
{
"key": "terminal",
"value": 1
},
{
"key": "note|status",
"value": "Some key orginal sample notes, Enabled"
},
{
"key": "group|level",
"value": "Low"
},
],
"name": "test 3",
"number": "128737812381723",
"id": "kasjdashdkaskjd"
}
]
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)
I have the following code snippet, where I want original array (filters) to be filtered and get unique filters array.
I think I tried all the methods possible and it (uniqueFilters array) is still same 11 member original array.
Whats wrong?
How can I ensure that this array is actually filtered down to just a few unique elements in it? (they all are coming from the same place and are the same)
UPDATE:
- the answer successfully resolved the issue in js code.
- in the actual app I had to also deal with typescript to use the suggested answer. So maybe will help someone:
let newUniqueFilters = Array.from(new Map(filters.map(f => [f._id, f] as [string, any])).values());
var filters = [{
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter2",
"filterIndex": 2,
"filterLabel": "Shadow",
"filterURL": "url(#filter2)",
"filterEffects": [{
"name": "feOffset",
"attributes": [{
"name": "dx",
"value": 20
}, {
"name": "dy",
"value": 20
}, {
"name": "result",
"value": "offOut"
}, {
"name": "in",
"value": "SourceAlpha"
}]
}, {
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 7
}, {
"name": "in",
"value": "offOut"
}, {
"name": "result",
"value": "blurOut"
}]
}, {
"name": "feBlend",
"attributes": [{
"name": "mode",
"value": "normal"
}, {
"name": "in2",
"value": "blurOut"
}, {
"name": "in",
"value": "SourceGraphic"
}]
}]
}, {
"_id": "filter2",
"filterIndex": 2,
"filterLabel": "Shadow",
"filterURL": "url(#filter2)",
"filterEffects": [{
"name": "feOffset",
"attributes": [{
"name": "dx",
"value": 20
}, {
"name": "dy",
"value": 20
}, {
"name": "result",
"value": "offOut"
}, {
"name": "in",
"value": "SourceAlpha"
}]
}, {
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 7
}, {
"name": "in",
"value": "offOut"
}, {
"name": "result",
"value": "blurOut"
}]
}, {
"name": "feBlend",
"attributes": [{
"name": "mode",
"value": "normal"
}, {
"name": "in2",
"value": "blurOut"
}, {
"name": "in",
"value": "SourceGraphic"
}]
}]
}, {
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter2",
"filterIndex": 2,
"filterLabel": "Shadow",
"filterURL": "url(#filter2)",
"filterEffects": [{
"name": "feOffset",
"attributes": [{
"name": "dx",
"value": 20
}, {
"name": "dy",
"value": 20
}, {
"name": "result",
"value": "offOut"
}, {
"name": "in",
"value": "SourceAlpha"
}]
}, {
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 7
}, {
"name": "in",
"value": "offOut"
}, {
"name": "result",
"value": "blurOut"
}]
}, {
"name": "feBlend",
"attributes": [{
"name": "mode",
"value": "normal"
}, {
"name": "in2",
"value": "blurOut"
}, {
"name": "in",
"value": "SourceGraphic"
}]
}]
}, {
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter2",
"filterIndex": 2,
"filterLabel": "Shadow",
"filterURL": "url(#filter2)",
"filterEffects": [{
"name": "feOffset",
"attributes": [{
"name": "dx",
"value": 20
}, {
"name": "dy",
"value": 20
}, {
"name": "result",
"value": "offOut"
}, {
"name": "in",
"value": "SourceAlpha"
}]
}, {
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 7
}, {
"name": "in",
"value": "offOut"
}, {
"name": "result",
"value": "blurOut"
}]
}, {
"name": "feBlend",
"attributes": [{
"name": "mode",
"value": "normal"
}, {
"name": "in2",
"value": "blurOut"
}, {
"name": "in",
"value": "SourceGraphic"
}]
}]
}, {
"_id": "filter1",
"filterIndex": 1,
"filterLabel": "Blur",
"filterURL": "url(#filter1)",
"filterEffects": [{
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 5
}]
}]
}, {
"_id": "filter2",
"filterIndex": 2,
"filterLabel": "Shadow",
"filterURL": "url(#filter2)",
"filterEffects": [{
"name": "feOffset",
"attributes": [{
"name": "dx",
"value": 20
}, {
"name": "dy",
"value": 20
}, {
"name": "result",
"value": "offOut"
}, {
"name": "in",
"value": "SourceAlpha"
}]
}, {
"name": "feGaussianBlur",
"attributes": [{
"name": "stdDeviation",
"value": 7
}, {
"name": "in",
"value": "offOut"
}, {
"name": "result",
"value": "blurOut"
}]
}, {
"name": "feBlend",
"attributes": [{
"name": "mode",
"value": "normal"
}, {
"name": "in2",
"value": "blurOut"
}, {
"name": "in",
"value": "SourceGraphic"
}]
}]
}]
// first method:
var uniqueFilters = [];
for(let i = 0; i < filters.length; i++) {
if(uniqueFilters.indexOf(filters[i]) == -1){
uniqueFilters.push(filters[i])
}
}
console.log("first method")
console.log("original array length:" + filters.length)
console.log("unique array length:" + uniqueFilters.length)
// second method:
//var uniqueFilters = filters.filter(function(elem, index, self) {
// return index == self.indexOf(elem);
//});
//console.log("second method")
//console.log("original array length:" + filters.length)
//console.log("unique array length:" + uniqueFilters.length)
// suggested method 1:
var newUniqueFilters = Array.from(new Map(filters.map(f => [f._id, f])).values());
console.log(newUniqueFilters)
You can use a Map:
filters = Array.from(new Map(filters.map(f => [f._id, f])).values());
This assumes that it is enough to compare the _id values, which uniquely identify filters.
Note that comparing objects themselves (with indexOf or similar methods) will never show duplicates, as all the objects are different references (copies), even though they look the same. In general {} === {} is always false.
It's not working because every element in filter array has different memory location and object are compared by the memory location.
So every time you compare that object exist of filter array in uniqueFilters, it simply doesn't exist because every object has different memory location.
so it will push every element in uniqueFilters.
Try changing this line
if(uniqueFilters.indexOf(filters[i]) == -1){
to
if(uniqueFilters.indexOf(filters[i]) === -1){
If not worikingn you can too try comparing a specific attibute to all uniqueFilter