Using Underscore restructure the JSON - javascript

Original JSON
var dataJson = [{
"MID" : "NTE",
"TNAME" : "gGAR",
"MVALUE" : 6
}, {
"MID" : "NTP",
"TNAME" : "gGAR",
"MVALUE" : 50
}, {
"MID" : "NTR",
"TNAME" : "gGAR",
"MVALUE" : 12
}, {
"MID" : "NTE",
"TNAME" : "gRRR",
"MVALUE" : 1
}, {
"MID" : "NTP",
"TNAME" : "gRRR",
"MVALUE" : 100
}, {
"MID" : "NTR",
"TNAME" : "gRRR",
"MVALUE" : 1
}];
Need to group by "TNAME" and after all the group taking first three objects based on "MID" and modify the JSON structure like
Expected output JSON:
var Convert = [
{
"GGARMVALUENTE":6,
"GGARMVALUENTP":50,
"GGARMVALUENTR":12,
"GRRRMVALUENTE":1,
"GRRRMVALUENTP":100,
"GRRRMVALUENTR":1
}
]

Finally it works according to your requirements. Just Solved Puzzling Question. :)
function restructure (data) {
let convert = []
let buffer = null
let pairs = data.map(d => {
return [`${d.TNAME.toUpperCase()}MVALUE${d.MID}`, d.MVALUE]
})
pairs.forEach((p, i) => {
let name = p.shift()
let value = p.shift()
let pair = {
[name]: value
}
if (buffer && buffer[name]) {
convert.push(buffer)
delete buffer
buffer = pair
} else {
if (buffer) {
Object.assign(buffer, pair)
} else {
buffer = pair
}
if (pairs.length === i + 1) {
convert.push(buffer)
delete buffer
}
}
})
return convert
}
console.log(restructure(dataJson))

Related

JavaScript: slice object name

"course_DxhYTv2copzWyBhKo" : {
"interest" : "DxhYTv2copzWyBhKo",
"type" : "course",
"affinity" : 3
}
From Object Name "course_DxhYTv2copzWyBhKo",
I want to slice "DxhYTv2copzWyBhKo"
Using String#split:
const data = {
"course_DxhYTv2copzWyBhKo" : {
"interest" : "DxhYTv2copzWyBhKo",
"type" : "course",
"affinity" : 3
}
};
const key = Object.keys(data)[0];
const sliceAfterSubStr = "course_";
const slicedSubStr = key.split(sliceAfterSubStr)[1];
console.log(slicedSubStr);
Using String#substr:
const data = {
"course_DxhYTv2copzWyBhKo" : {
"interest" : "DxhYTv2copzWyBhKo",
"type" : "course",
"affinity" : 3
}
};
const key = Object.keys(data)[0];
const sliceAfterSubStr = "course_";
const sliceIndex = key.indexOf(sliceAfterSubStr);
const slicedSubStr = sliceIndex !== -1
? key.substr( sliceIndex + sliceAfterSubStr.length )
: undefined;
console.log(slicedSubStr);
You can use the split operation on a string. Take a look at the following code snippet.
const courses = {
"course_DxhYTv2copzWyBhKo": {
"interest": "DxhYTv2copzWyBhKo",
"type": "course",
"affinity": 3
},
"course_DSdasdnDASnoiddDs": {
"interest": "DSdasdnDASnoiddDs",
"type": "course",
"affinity": 3
}
}
console.log(Object.keys(courses).map(key => key.split("_")[1]))

How can I remove duplicates in an array of object?

I have an array which looks like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
},
]
}
]
I want to remove duplicate itemP so with a function it will look like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : null
},
]
}
]
When I try I always have errors. It is possible to do this?
Update
I try to do this :
console.log(array.map(pack =>
pack.values.map((item) => {
var test = JSON.stringify(item)
var set = new Set(test)
return Array.from(set).map((item)=> JSON.parse(item))
}
)
))
Unexpected end of JSON input
I also try something will filter but it doesn't work:
console.log(this.package.map(pack => pack.values.filter(
(value, index , array) => array.itemP.indexOf(value) === index
)))
Instead of mapping every key property, I suggest cloning the whole structure and setting the object value as null in the cloned one, avoiding unintentionally mutating the original structure.
function nullifyDupes(array) {
const clone = JSON.parse(JSON.stringify(array));
const seen = {};
clone.forEach(pack => {
pack.values.forEach(items => {
for (const item in items) {
const id = items[item].id;
if (seen[id]) items[item] = null;
else seen[id] = true;
}
});
});
return clone;
}
const originalArray = [{
key : { id : 1 , pack : "pack 1"},
values : [{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}]
}];
const mutatedArray = nullifyDupes(originalArray);
console.log(mutatedArray);
To achieve expected result, use below option of using map
Loop array using map
Use nameArr to check duplicate and assigning null value
Loop values array and check the name in nameArr using indexOf and assign null
var array = [
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
}
]
console.log(array.map(v => {
let nameArr = []
v.values = v.values.map(val => {
if(nameArr.indexOf(val.itemP.name) !== -1){
val.itemP.name = null
}else{
nameArr.push(val.itemP.name)
}
return val
})
return v
}))
You can use map and an object to check if its already exist. Like
var obj = {}
and loop over values
var values = [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
values.map((v) => {
if(!obj[v.itemP.id + '-' + v.itemP.name]) {
obj[v.itemP.id + '-' + v.itemP.name] = true;
return v;
}
return { item : v.item }
})
You can map your array elements to array objects which don't include your duplicates using .map(). For each iteration of .map() you can again use .map() for your inner values array to convert it into an array of objects such that the duplicates are converted to null. Here I have kept a seen object which keeps track of the properties seen and their stringified values. By looping over all the properties in your object (using for...of), you can work out whether or not the key-value pair has been seen before by using the seen object.
The advantage of this approach is that it doesn't just work with one property (ie not just itemP), but it will work with any other duplicating key-value pairs.
See example below:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
const seen = {};
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
for (let p in vobj) {
vobj[p] = seen[p] === JSON.stringify(vobj[p]) ? null : vobj[p];
seen[p] = seen[p] || JSON.stringify(vobj[p]);
}
return vobj;
});
return obj;
});
console.log(res);
For an approach which just removed itemP from all object in accross your array you can use:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
let itemP = "";
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
vobj.itemP = itemP ? null : vobj.itemP;
if('itemP' in vobj) {
itemP = itemP || JSON.stringify(vobj.itemP);
}
return vobj;
});
return obj;
});
console.log(res);

group array of objects by property first letter

im struggling a little with this, been a while since ive coded javascript ... trying to convert this
items = {
"data": [
{
"name" : "john"
},
{
"name" : "james"
},
{
"name" : "joe"
},
{
"name" : "brian"
},
{
"name" : "bojan"
},
{
"name" : "billy"
},
{
"name" : "dean"
},
{
"name" : "darren"
},
{
"name" : "doug"
}
]
}
into this format
items = {
"data": [
{
letter: "j"
names : ["john", "james", "joe"]
},
{
letter: "b"
names : ["brian", "bojan", "billy"]
},
{
letter: "j"
names : ["dean", "darren", "doug"]
},
]
}
I've been trying to do this using reduce but not having much look.... is there a simpler way to to do it?
You can use reduce to create an object with the letters as keys from which you can extrapolate the array of objects you need by iterating over the object entries using map.
const items = {"data":[{"name":"john"},{"name":"james"},{"name":"joe"},{"name":"brian"},{"name":"bojan"},{"name":"billy"},{"name":"dean"},{"name":"darren"},{"name":"doug"}]};
// `reduce` over the data to produce an object
// with letter keys, and array values where the names are added
const obj = items.data.reduce((acc, c) => {
const letter = c.name[0];
acc[letter] = (acc[letter] || []).concat(c.name);
return acc;
}, {})
// `map` over the object entries to return an array of objects
items.data = Object.entries(obj).map(([letter, names]) => {
return { letter, names }
}).sort((a, b) => a.letter > b.letter);
console.log(items);
Vanilla javascript implementation:
const items = {
"data": [
{
"name" : "john"
},
{
"name" : "james"
},
{
"name" : "joe"
},
{
"name" : "brian"
},
{
"name" : "bojan"
},
{
"name" : "billy"
},
{
"name" : "dean"
},
{
"name" : "darren"
},
{
"name" : "doug"
}
]
}
const transformed = {
data:[]
}
const findByLetter = (letter) => (element) => element.letter === letter;
for(let i = 0; i < items.data.length; i++){
const letter = items.data[i].name.split("")[0];
const elIndex = transformed.data.findIndex(findByLetter(letter));
if(elIndex > -1){
transformed.data[elIndex].names.push(items.data[i].name);
}else{
transformed.data.push({
letter,
names: [items.data[i].name],
});
}
};
console.log(transformed);
Use one reduce():
const items = {"data":[{"name":"john"},{"name":"james"},{"name":"joe"},{"name":"brian"},{"name":"bojan"},{"name":"billy"},{"name":"dean"},{"name":"darren"},{"name":"doug"}]};
let res = items.data.reduce((acc, item) => {
let l = item.name[0];
if (acc.data.filter(e => e.letter == l)[0] === undefined) acc.data.push({'letter': l, names: [] });
acc.data.filter(e => e.letter == l)[0].names.push(item.name);
return acc;
}, {"data": []})
console.log(res)

Created a nested Json structure from an Javascript array

I'm looking to create a valid nested Json file, from an array, with unique keys value. Currently, I'm only able to to display the json without any nested structure.
I would like to display to the console the following structure :
{
"Key" : "data1",
"header" : {
"title" : "data2",
"tag1" : "data3",
"tag2" : "data4"
},
"body" : {
"text" : "data5"
},
"updates" : {
"title" : "data6",
"text" : "data7"
},
"footer" : {
"title" : "data8",
"row1" :{
"col1" : {
"title" : "data9",
"text" : "data10"
},
"col2" : {
"title" : "data11",
"text" : "data12"
},
"col3" : {
"title" : "data13",
"text" : "data14"
}
},
"row2" :{
"col1" : {
"title" : "data15",
"text" : "data16"
},
"col2" : {
"title" : "data17",
"text" : "data18"
},
"col3" : {
"title" : "data19",
"text" : "data20"
}
},
"row3" :{
"col1" : {
"title" : "data22",
"text" : "data23"
},
"col2" : {
"title" : "data24",
"titlebis" : "data25",
"text" : "data26"
},
"col3" : {
"title" : "data27",
"text" : "data28"
}
},
"row4" :{
"col1" : {
"title" : "data29"
},
"website" : "data30",
"website-link" : "data31",
"email" : "data38",
"privacy" : "data32",
"privacy-link" : "data33",
"adr" : "data34",
"adr2" : "data35"
}
},
"other" : {
"short" : {
"des" : "data36"
},
"promovideo" : "data37"
}
}
here is what I already done:
var data = [["Key", "data1"],
["header.title", "data2"],
["header.tag1", "data3"],
["header.tag2", "data4"],
["body.text", "data5"],
["updates.title", "data6"],
["updates.text", "data7"],
["footer.title", "data8"],
["footer.row1.col1.title", "data9"],
["footer.row1.col1.text", "data10"],
["footer.row1.col2.title", "data11"],
["footer.row1.col2.text", "data12"],
["footer.row1.col3.title", "data13"],
["footer.row1.col3.text", "data14"],
["footer.row2.col1.title", "data15"],
["footer.row2.col1.text", "data16"],
["footer.row2.col2.title", "data17"],
["footer.row2.col2.text2", "data18"],
["footer.row2.col3.title", "data19"],
["footer.row2.col3.text", "data20"],
["footer.row3.col1.title", "data22"],
["footer.row3.col1.text", "data23"],
["footer.row3.col2.title", "data24"],
["footer.row3.col2.title", "data25"],
["footer.row3.col2.text", "data26"],
["footer.row3.col3.title", "data27"],
["footer.row3.col3.text", "data28"],
["footer.row4.col1.title", "data29"],
["footer.row4.website", "data30"],
["footer.row4.website-link", "data31"],
["footer.row4.email", "data31"],
["footer.row4.privacy", "data32"],
["footer.row4.privacy-link", "data33"],
["footer.row4.adr", "data34"],
["footer.row4.adr2", "data35"],
["other.short.des", "data36"],
["other.promovideo", "data37"],
];
// console.log(data);
data.sort(alphabetical); // Sort alphabetically our 2D array
CreateAndDisplayJson(data);
// Create a JSON file from Keys Trad Data
function CreateAndDisplayJson(GetKeysTraductionArrayData) {
var lenght = GetKeysTraductionArrayData.length;
var output = "{\n";
for (var i = 0; i < GetKeysTraductionArrayData.length; i++) {
var key = GetKeysTraductionArrayData[i][0];
var trad = GetKeysTraductionArrayData[i][1];
var nameSplit = key.split("."); // Check how many times we need to indent json from Key
if(nameSplit.length>1) { // The Key needs to be indented
var closeBraket = "";
var spacing = ""; // Json indentation
var saveSpacingTab = []; // Closing indentation
for (j=0; j <nameSplit.length; j++){ // We add the key + indentation
output += spacing+"\""+nameSplit[j]+"\" : { \n";
if (j==0 && i != GetKeysTraductionArrayData.length-1) {
closeBraket = spacing+"}, \n";
} else {
closeBraket = spacing+"} \n";
}
spacing +=" ";
saveSpacingTab[j] = closeBraket;
closingText = "";
if (j==nameSplit.length-1) { // last indentation of the Key
saveSpacingTab.reverse();
for ( k=0; k < saveSpacingTab.length ; k++) { // We create the Bracket indentation
closingText += saveSpacingTab[k];
}
output += spacing+"\""+nameSplit[j]+"\" : " + "\""+trad +"\"\n" + closingText; // last Row
}
}
} else {
output += "\""+key+"\" : " + "\""+trad +"\", \n";
}
}
// output += "}" + outputCommented;
output += "}";
console.log(output);
return output;
}
// Sort alphabetically our 2D array
function alphabetical(a, b) {
var A = a[0];
var B = b[0].toLowerCase();
A = A.toLowerCase();
B = B.toLowerCase();
if (A < B) return -1;
if (A > B) return 1;
return 0;
}
You can use forEach loop and inside split each key and then use reduce to build nested structure for each key.
var data = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]
let result = {}
data.forEach(([key, value]) => {
key.split('.').reduce((r, k, i, arr) => {
return r[k] || (r[k] = arr[i + 1] ? {} : value)
}, result)
})
console.log(result)
A non-ternary solution with reduce:
const data = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]
const result = data.reduce((all, [keys, val]) => {
keys.split('.').reduce((obj, key, i, arr) => {
if (i === arr.length - 1) {
obj[key] = val;
} else {
if (!obj.hasOwnProperty(key)) {
obj[key] = {};
};
}
return obj[key];
}, all);
return all;
}, {});
console.log(result);

I don't know how to implementate the function reduce

I do not know how to implement the reduce function.
I have output from my map a document as ...
for example two documents
key "_id":"AD"
"values"
{
"numtweets" : 1,
"hastags" : {
"OPINIÓ" : 1,
"debat" : 1,
"inexistent" : 1,
"tampoc" : 1,
"promet" : 1,
"gaire" : 1,
"diàleg" : 1
}
}
and other
{
"numtweets" : 1,
"hastags" : {
"other" : 1,
"debat" : 1,
"inexistent" : 1,
"another" : 1,
}
}
I need a function that reduces all sum so that
"numtweets" : 2,
"dicwords" : {
"OPINIÓ" : 1,
"debat" : 2,
"inexistent" : 2,
"tampoc" : 1,
"promet" : 1,
"gaire" : 1,
"diàleg" : 1,
"other" : 1,
"another" : 1
},
"lisuser" : {
"user2" : 1
}
if my json values was only nuwtweets the reduce is
function(key, values) {
return Array.sum(values);
};
if mi json values only was hastags (without numtweets and lisuser) the reduce function was
var r = function(key, values) {
result = {}
values.forEach(function(val) {
for (hashtag in val) {
if (hashtag in result) {
result[hashtag] = result[hashtag] + val[hashtag]
} else {
result[hashtag] = val[hashtag]
}
}
});
return(result)
};
But I don't know how mix the 2 reduce function.
My level of mongodb and JavaScript is very low.
Thanks
Try this:
let data = values.reduce((finalObj, ele) => {
finalObj.numtweets += ele.numtweets
for (key in ele.hastags) {
if(ele.hastags.hasOwnProperty(key)) {
if(finalObj.hastags[key])
finalObj.hastags[key] += ele.hastags[key]
else
finalObj.hastags[key] = ele.hastags[key]
}
}
return finalObj
})
console.log(data)
Where values is array for objects which you want reduce to one object

Categories