Javascript way of performing basic merge on two object [duplicate] - javascript

This question already has answers here:
Merge two javascript objects adding values of common properties
(4 answers)
How to merge objects and sum just some values of duplicate objects? [duplicate]
(1 answer)
Closed 2 years ago.
I have two objects that look like:
{
"data" : [
{
"name" : "toyota",
"type" : "cars",
"totals" : {
"invalid" : 4,
"valid" : 14,
"percentage" : 77.78,
"total" : 18
}
}
],
"report_id": "123wa31a22aba05"
}
I would like to merge those two objects into one object with the following set of rules:
Every two cars that have the same name and type in the data should be merged. This means that totals will be:
"totals": {
"invalid": "invalidA" + "invalidB"
"valid": "validA" + "validB"
"percentage" : calculatePercentage("invalid","valid")
"total": "invalid" + "valid"
}
If there is only sub-object with some name and type, it will just push it as it to the merged report.
What I thought: Copy object one to result object. Then iterate over the second object and insert the elements into the result object (merge if needed). I would use the for loop as I'm used from Java, but it doesn't feel a good js code. What is the proper way to merge those two object in JS?
Example to make it easier:
Object 1:
{
"data" : [
{
"name" : "toyota",
"type" : "cars",
"totals" : {
"invalid" : 4,
"valid" : 14,
"percentage" : 77.78,
"total" : 18
}
}
],
"report_id": "123wa31a22aba05"
}
Object 2:
{
"data" : [
{
"name" : "toyota",
"type" : "cars",
"totals" : {
"invalid" : 2,
"valid" : 5,
"percentage" : 71.42,
"total" : 7
}
}
],
"report_id": "123wa31a22aba06"
}
Result:
{
"data" : [
{
"name" : "toyota",
"type" : "cars",
"totals" : {
"invalid" : 6,
"valid" : 19,
"percentage" : 76.0,
"total" : 25
}
}
]
}

This solution might help you.
var a = {
"data": [
{
"name": "toyota",
"type": "cars",
"totals": {
"invalid": 4,
"valid": 14,
"percentage": 77.78,
"total": 18
}
}
],
"report_id": "123wa31a22aba05"
},
b = {
"data": [
{
"name": "toyota",
"type": "cars",
"totals": {
"invalid": 2,
"valid": 5,
"percentage": 71.42,
"total": 7
}
}
],
"report_id": "123wa31a22aba06"
},
c = [...a.data, ...b.data];
var tmp = [];
for (let i = 0; i < c.length; i++) {
for (let j = i + 1; j < c.length; j++) {
if(c[i].name == c[j].name) {
c[i].totals.invalid += c[j].totals.invalid;
c[i].totals.valid += c[j].totals.valid;
c[i].totals.total += c[j].totals.total;
c[i].totals.percentage = (c[i].totals.valid / c[i].totals.total) * 100;
c.splice(j, 1)
}
}
}
console.log(c);

Related

Getting empty data while trying to get desired format of object

I have an object
"data" : [
{
"name" : "Heading",
"text" : "Text Heading",
"type" : "string",
"values" : [
"Arthur"
]
},
{
"name" : "Source",
"text" : "Source Reference",
"type" : "string",
"values" : [
"Jhon"
]
},
{
"name" : "Place",
"text" : "Bank Building",
"type" : "string",
"values" : [
"Mark"
]
},
{
"name" : "Animal",
"text" : "Branch",
"type" : "string",
"values" : [
"Susan"
]
}
]
there is a function i am passing the object and an array as the arguments
fieldArray=["Heading", "Animal"]
myFunction(fieldArray, data){
... your code here
}
I need to get the output in the below format where I have to search the object with the fields in myArray with the name key of data. Then I need to put the value of the searched object in the below format
[{
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": "Heading"
},
{
"id": "ConstValue",
"cellContent": "Arthur"
}
]
},
{
"id": 2,
"cells": [{
"id": "ConstId",
"cellContent": "Animal"
},
{
"id": "ConstValue", //a constant field name as ConstValue
"cellContent": "Susan" // the value of the second field in the myArray from object with name Animal
}
]
}
]
I have tried this
const getFormattedData = (fieldArray: any, data: any) => {
let innerData: any = [];
for (let i=0; i<fieldArray.length; i++){
const indexNumber = data.find((key: any) => key.name === fieldArray[i])
if(indexNumber != undefined){
innerData.push({
id: i+1,
cells:[{
id: 'inquiryName',
cellContent: indexNumber.name
},
{
id: 'value',
cellContent: indexNumber.values.toString()
}
]
})
}
console.log('innerData :>> ', innerData);
}
}
You could use the below. Since you tagged javascript, posting answer in JS.
function formatData(data, fieldArray) {
let ret = [];
fieldArray.forEach((field, i) => {
let dataObj = data.filter(d => d.name === field)[0]
if( dataObj ) {
ret.push({
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": field
},
{
"id": "ConstValue",
"cellContent": dataObj.values[0] //Put whole obj or just first
}
]
})
}
})
return ret;
}
Link to plnkr

How to display all fields of a nested json in table format using Bootstrap

I want to write a utility which connects to a REST api downloads data in JSON format and then paints the data as nested tables using Bootstrap.
JSON Data -
[
{
"id" : "Id1",
"name" : "Name1",
"orders" : [{"orderId" : "o1", "size" : 34}, {"orderId" : "o2", "size" : 3}]
},
{
"id" : "Id2",
"name" : "Name2",
"orders" : [
{"orderId" : "o3", "size" : 5, "addresses" : [{"addressId" : "a1", "phone" : "1235"}, {"addressId" : "a2", "phone" : 555}]},
{"orderId" : "o4", "size" : 5, "addresses" : [{"addressId" : "a3", "phone" : "1235"}]}
]
}
]
I looked at the sub-table feature of Bootstrap, however it seems that it would need lot of custom code to get this working. Is there a better way to bind the json to table in a generic way?
Edit
After spending some time I was able to achieve this -
As you can see, I could get one level of nesting, however i just need to go one level deep. Any suggestions?
<script>
var $table = $('#table')
function buildTable($el, jsonData) {
var i; var j; var row
var columns = []
var data = []
if(!Array.isArray(jsonData) && jsonData.length == 0) {
return;
}
Object.keys(jsonData[0]).forEach( (k) => {
columns.push({
field: k,
title: k,
sortable: true
})
})
for(var j = 0; j < jsonData.length; j++) {
row = {}
Object.keys(jsonData[j]).forEach( (k) => {
row[k] = jsonData[j][k]
})
data.push(row)
}
$el.bootstrapTable({
columns: columns,
data: data,
detailFilter: function (index, row) {
console.log("detail filter " + Object.values(row))
for(var k in row) {
if(Array.isArray(row[k])){
return true;
}
}
return false;
},
onExpandRow: function (index, row, $detail) {
console.log("expand row keys " + Object.keys(row))
console.log("expand row vals " + Object.values(row))
var newRow = {};
for(var k in row) {
if(Array.isArray(row[k])){
alert('found ' + row[k])
newRow = row[k]
break
}
}
buildTable($detail.html('<table></table>').find('table'), newRow)
}
})
};
var mydata =
[
{
"id": 0,
"name": "test0",
"price": "$0",
"orders" :
[
{
"name" : "ABC",
"size" : 25,
"someList": [{"a":1, "b":2}, {"a":3, "b":4}]
},
{
"name" : "XYZ",
"size" : 50
}
]
}
/* {
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2",
"orders" : [{"name" : "def", "size": 45}]
}*/
];
$(function() {
buildTable($table, mydata)
})

Access title inside id

I am having trouble to access title inside an ID object.
I want to access item.title. But i am not able to give a name to the object ID.
I tried doing order.cart.items.item.title
"_id" : ObjectId("5d60d1752cda6403e4f868af"),
"created_at" : ISODate("2019-08-24T05:55:34.741Z"),
"user" : ObjectId("5d60d00e4c865312ccf3f18a"),
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
},
You need to use Object.values for that, because of the ID. This allows you to get the object with the key of 5d60cddb69f460191c680e96 without the key:
Object.values(order.cart.items)[0].item.title
const data = {
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
}};
for (let id in data.cart.items)
console.log(data.cart.items[id].item.title);
You can simply achieve this by getting key name of an object using Object.keys() methods, This methods returns an array of key names
const obj = { id: 1 };
const keysArray = Object.keys(obj);
console.log(keysArray);. // ["id"]
In your case only one keys are present in the object, So we can directly get that name with index 0 (Object.keys(obj)[0])
Check below snippet
const cart ={
"items": {
"5d60cddb69f460191c680e96": {
"item": {
"_id":
"5d60cddb69f460191c680e96",
"imagePath": '',
"title": "Nike ",
"description": "Nike",
"price": 10,
"category": "shoes",
"__v": 0
},
"qty": 1,
"price": 10
}
}
};
const id =
Object.keys(cart.items)[0];
console.log(
cart.items[id].item.title
);

How can i get pair of the json object in javascript

data =
{"user" : [
{
"id" : 1,
"name" : "jeboo",
"level": 1
},
{
"id" : 2,
"name" : "yoyo",
"level": 1
},
{
"id" : 3,
"name" : "yaya",
"level": 2
},
{
"id" : 4,
"name" : "yeye",
"level": 2
},
{
"id" : 5,
"name" : "yiyi",
"level": 3
},
{
"id" : 6,
"name" : "jebee",
"level": 3
}
]}
this is how i get json object
var obj = JSON.stringify(data);
var parse = JSON.parse(obj);
$.each(parse, function(key, object) {
$.each(object, function(index, val) {
console.log(index, val);
});
});
my purpose is want to produce the array below
object 0 + object 1 = first pair
object 2 + object 3 = second pair
object 4 + object 5 = third pair
Assuming you want objects with same level in pairs,
You can use Array#reduce to achieve this:
var data =
{"user" : [
{
"id" : 1,
"name" : "jeboo",
"level": 1
},
{
"id" : 2,
"name" : "yoyo",
"level": 1
},
{
"id" : 3,
"name" : "yaya",
"level": 2
},
{
"id" : 4,
"name" : "yeye",
"level": 2
},
{
"id" : 5,
"name" : "yiyi",
"level": 3
},
{
"id" : 6,
"name" : "jebee",
"level": 3
}
]};
var r = data.user.reduce(function(res, obj) {
res[obj.level - 1] = res[obj.level - 1] || [];
res[obj.level - 1].push(obj);
return res;
}, []);
console.log(r);
EDIT
If you want to pair the objects according to their position in the array and independent of level property then you can use callback's index argument and a bit of math:
var r = data.user.reduce(function(res, obj, idx) {
res[Math.floor(idx/2)] = res[Math.floor(idx/2)] || [];
res[Math.floor(idx/2)].push(obj);
return res;
}, []);

Trying to get the sum for each Object

I have been trying to figure this out, but I seem to be going nowhere. Basically I have a JSON that outputs.
[
{
"gosuResponse" : {
"tokenId" : "60e2d532-3d1c-4a95-adbd-aa352984c125",
"page" : 1,
"pageSize" : 1000,
"nbLinesTotal" : 15,
"serials" : {
"serial" : [ "272072207980" ]
},
"data" : {
"row" : [ {
"col" : [ "2015-02-10", "", "1"]
}, {
"col" : [ "2015-02-10", "BNP-Blogs", "1504"]
}, {
"col" : [ "2015-02-10", "BNP", "66"]
}, {
"col" : [ "2015-02-10", "GOOMPlayer-Site", "6"]
}, {
"col" : [ "2015-02-10", "podcast", "19"]
}, {
"col" : [ "2015-02-10", "stream", "10"]
}, {
"col" : [ "2015-02-09", "", "6"]
}, {
"col" : [ "2015-02-09", "BNP-Blogs", "1742"]
}, {
"col" : [ "2015-02-09", "BNP", "61"]
}, {
"col" : [ "2015-02-09", "GOOMPlayer-Site", "2"]
}, {
"col" : [ "2015-02-09", "podcast", "18"]
}, {
"col" : [ "2015-02-09", "stream", "8"]
}, {
"col" : [ "2015-02-08", "", "7"]
}, {
"col" : [ "2015-02-01", "stream", "8"]
} ]
}
}
}
]
Since there are similar names, I grouped them together using underscore.js
var items = result[0].gosuResponse.data.row;
var groups = _(items).groupBy(function(o) {
return o.col[1];
});
console.log(groups);
This outputs,
Object
- BNP : Array[4]
- 0 : Object
- col : Array[3]
0 : '2015-02-10"
1 : 'BNP'
2: '66'
- 1 : Object
- col : Array[3]
0 : '2015-02-10"
1 : 'BNP'
2: '66'
I am trying to add up the number value in position 2 for each Object.
I tested with one key in my Plunkr, but I was wondering if there is a way to do it for all objects?
My Plunkr http://plnkr.co/edit/nNwNoAiUz4PKV8ucaPc1?p=preview
I think there is no reasons to group items:
var sum = {};
_.each(items, function(row) {
var col = row.col;
if (sum.hasOwnProperty(col[1])) {
sum[col[1]] += parseInt(col[2]) || 0;
} else {
sum[col[1]] = parseInt(col[2]) || 0;
}
});
But note I'm relatively new to underscore.js and did not know much about its specific tricks.
Update:
I've found a native underscore.js solution with using groups also:
var groups = _(items).groupBy(function(o) {
return o.col[1];
});
var sum2 = {};
_.each(groups, function(group, key) {
sum2[key] = _.reduce(group, function(memo, item) {
return memo + (parseInt(item.col[2]) || 0);
}, 0);
});

Categories

Resources