combine the two JSON Objects depending on the ids - javascript

I am trying to combine two JSON objects using angular and create a single object. somehow i am able to do it but a small glitch not able to find what can be done for that .. below are the two JSON objects:
var array1 = [
{
"personId" : 7,
"batchNumber": 213,
"name": "Mike",
"company":"abc"
}];
var array2 = [
{
"batchNumber": 213,
"role": "engineer"
},
{
"batchNumber": 213,
"role": "architect"
}];
i want the resultant json to be
var result = [
{
"personId" : 7,
"batchNumber": 213,
"name": "Mike",
"company":"abc",
"role": "engineer"
}
{
"personId" : 7,
"batchNumber": 213,
"name": "Mike",
"company":"abc",
"role": "architect"
}]
I am able to create only one json out of it and then the loop is terminated/ Any help would be grateful thanks in advance.
var array1 = [{
"personId" : 7,
"batchNumber": 213,
"name": "Mike",
"company":"abc"
}, {
"personId" : 8,
"batchNumber": 218,
"name": "julie",
"company":"tyu"
}];
var array2 = [{
"batchNumber": 213,
"role": "engineer"
},
{
"batchNumber": 213,
"role": "architect"
},{
"batchNumber": 218,
"role": "BSA"
},
{
"batchNumber": 218,
"role": "Manager"
}];
var newArray = [];
for (var i = 0; i < array1.length; i++) {
var obj = array1[i];
if (array2[i] && obj.box == array2[i]._id) {
for (key in array2[i]) {
obj[key] = array2[i][key];
}
newArray.push(obj);
}
};
console.log(newArray);
I'm attaching the JS fiddle as well: https://jsfiddle.net/n9pv4pL3/
My Controller:
var array1 = [
{
"personId" : 7,
"batchNumber": 213,
"name": "Mike",
"company":"abc"
}];
var array2 = [
{
"batchNumber": 213,
"role": "engineer"
},
{
"batchNumber": 213,
"role": "architect"
}];
var newArray = [], i,key;
for (var i = 0; i < array2.length; i++) {
var obj = array2[i];
if (array1[i] && obj. INPT_FILE_ID == array1[i].INPT_FILE_ID) {
for (key in array1[i]) {
obj[key] = array1[i][key];
}
newArray.push(obj);
}
};
console.log(newArray);

var array1 = [
{
"personId": 7,
"batchNumber": 213,
"name": "Mike",
"company": "abc"
}];
var array2 = [
{
"batchNumber": 213,
"role": "engineer"
},
{
"batchNumber": 213,
"role": "architect"
}];
var finalData = [];
array1.forEach(data => {
//filter batchwise data
var dataFromArray2 = array2.filter(arry2 => {
return arry2.batchNumber === data.batchNumber });
//pushing data in main array
dataFromArray2.forEach(batchData => {
finalData.push({
personId: data.personId,
batchNumber: batchData.batchNumber,
name: data.name,
company: data.company,
role: batchData.role
});
});
});
console.log(finalData)
here it's run fine,please check it once again,I have also added snippet for that
and about filter method
which is Returns the new filtered array.
in our case it's return new array with all properties of array2
if you want to understand in deap then refer this link
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Ok if you want to aggregate all roles under one key you could do it with 2 reduce functions like this:
let workingArray = array1.reduce((prevVal, currVal, index) => {
let role = array2.reduce((rPrevVal, rCurrVal, idx) => {
if (currVal.batchNumber === rCurrVal.batchNumber) {
rPrevVal.push(rCurrVal.role);
}
return rPrevVal;
}, []);
prevVal.push({
...currVal,
role
});
return prevVal;
}, []);
console.log(workingArray);
There's probably less complex solution, but what can I say I like reduce function:) Check fiddle here (in console) I added 2 different objects in first array and more objects in second:
https://fiddle.jshell.net/pegla/v4qqs3dk/2/

Related

Remove JSON attributes if not found in defined array

I need to remove attribute from the meta if it's not exist in att
for example : cardNo is not existing in the att
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
Expected output:
[
{
"id": 1,
"name": "test",
},
{
"id": 2,
"name": "test2"
}
];
for(let data of meta){
for (let key of Object.keys(data)) {
if (arr.indexOf(key) == -1) {
delete obj[key];
}
} }
Use Ramda.js (https://ramdajs.com/docs/) to make it easier:
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
]
const onlyAtts = map(pick(att), meta)
i think this is the answer for your question.
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
let newMeta = meta.map((d) => {
let obj = {};
att.forEach((currentAtt) => {
if(d.hasOwnProperty(currentAtt)) {
obj[currentAtt] = d[currentAtt];
}
});
return obj;
});
console.log(newMeta);
You can easily achieve this using map and reduce.
const att = ["id", "name", "class"];
const meta = [
{
id: 1,
name: "test",
cardNo: 23,
},
{
id: 2,
name: "test2",
cardNo: 232,
},
];
const result = meta.map((obj) => {
const perfectObj = att.reduce((acc, curr) => {
if (obj[curr]) {
acc[curr] = obj[curr];
}
return acc;
}, {});
return perfectObj;
});
console.log(result);
This is also works
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
function compare(meta, fields) {
meta.map(object => {
let dataKeys = Object.keys(object);
dataKeys.forEach(element => {
if(fields.indexOf(element) < 0) {
delete object[element];
}
});
});
}
compare(meta, att);
console.log(meta);

Combining same objects in json array javascript

I have this array:
[{ "id": 1, "myId": "100", "name": "amey" }, { "id": 2, "myId": "100", "name": "anuj" }, { "id": 3, "myId": "101", "name": "suraj" }, { "id": 4, "myId": "101", "name": "suraj h" }]
I want output like this:
[{ "id": 1, "myId": "100", "name": ["amey", "anuj"] }, { "id": 3, "myId": "101", "name": ["suraj", "suraj h] }]
How can I do this using javascript
for (var i = 0; i < myarray.length; i++) {
//And loop again for duplicate data
for (var j = i + 1; j < myarray.length; j++) {
if (
myarray[i].VENDOR_ID == myarray[j].VENDOR_ID &&
myarray[i].ORDER_ID === myarray[j].ORDER_ID
) {
var tmp = myarray[j].NAME;
console.log(tmp);
myarray[j].NAME = [];
myarray[j].NAME.push(tmp);
myarray[j].NAME.push(myarray[i].NAME);
myarray[i] = {};
}
}
}
You can use an array reduce into an object and return the array of values. Reduce into an object using the myId property as the key to group by. Shallow copy any existing state and and name array, appending the new name value from the current element.
Object.values(
input.reduce(
(acc, { id, myId, name }) => ({
...acc,
[myId]: {
...(acc[myId] || { id, myId }),
name: [...(acc[myId]?.name || []), name]
}
}),
{}
)
const input = [
{ id: 1, myId: "100", name: "amey" },
{ id: 2, myId: "100", name: "anuj" },
{ id: 3, myId: "101", name: "suraj" },
{ id: 4, myId: "101", name: "suraj h" }
];
const res = Object.values(
input.reduce(
(acc, { id, myId, name }) => ({
...acc,
[myId]: {
...(acc[myId] || { id, myId }),
name: [...(acc[myId]?.name || []), name]
}
}),
{}
)
);
console.log(JSON.stringify(res));
You can use Array.prototype.reduce():
const arr1 = [{
"id": 1,
"myId": "100",
"name": "amey"
}, {
"id": 2,
"myId": "100",
"name": "anuj"
}, {
"id": 3,
"myId": "101",
"name": "suraj"
}, {
"id": 4,
"myId": "101",
"name": "suraj h"
}]
const reduced = arr1.reduce((acc, item) => {
// 1. check if the 'acc' array already contains an item with the same 'myId' attribute
const itemIndex = acc.findIndex(it => it.myId === item.myId);
// 2. if there isn't any, push into the 'acc' array a copy of the item,
// with the 'name' property converted into an array of strings
// otherwise simply push the 'name' into the already existing item
if (itemIndex === -1) {
acc.push({
...item,
name: [item.name]
});
} else {
acc[itemIndex].name.push(item.name)
}
return acc;
}, []);
// test
console.log(reduced);

Comparing the keys of two JavaScript objects

I've got two sets of JavaScript objects. I want to compare object1 to object2, and then get a list of all the keys that are in object1, but not in object2. I've searching for resources to help me, but I've only ended up finding comparison functions for simple objects. The objects that I want to compare have a lot of nesting. I've included an example at the bottom.
How would I go about making a function for comparing these two objects? Is it possible to create a flexible function, that would also work if the objects were to change and contain more nesting?
const object1 = {
"gender": "man",
"age": 33,
"origin": "USA",
"jobinfo": {
"type": "teacher",
"school": "Wisconsin"
},
"children": [
{
"name": "Daniel",
"age": 12,
"pets": [
{
"type": "cat",
"name": "Willy",
"age": 2
},
{
"type": "dog",
"name": "jimmie",
"age": 5
}
]
},
{
"name": "Martin",
"age": 14,
"pets": [
{
"type": "bird",
"name": "wagner",
"age": 12
}
]
}
],
"hobbies": {
"type": "football",
"sponsor": {
"name": "Pepsi",
"sponsorAmount": 1000,
"contact": {
"name": "Leon",
"age": 59,
"children": [
{
"name": "James",
"pets": [
{
"type": "dog",
"age": 4
}
]
}
]
}
}
}
}
const object2 = {
"gender": "man",
"jobinfo": {
"type": "teacher"
},
"children": [
{
"name": "Daniel",
"age": 12,
"pets": [
{
"type": "cat",
"name": "Willy",
"age": 2
},
{
"type": "dog",
"name": "jimmie",
"age": 5
}
]
}
]
}
So what I want to achieve by comparing these two objects, is in this case to have an array return that consists of the keys that are in object1, but not object2. So the array would look something like this.
["age", "hobbies", "type", "sponsor", "name", "sponsorAmount", "contact", "name", "age", "children", "name", "pets", "type", "age"].
This is what I've gotten to so far. This is sort of working. But it's not printing out age for example, because age is a property that exists in multiple of the nested objects.
jsfiddle: https://jsfiddle.net/rqdgojq2/
I've had a look at the following resources:
https://stackoverflow.com/a/25175871/4623493
https://stackoverflow.com/a/21584651/4623493
Complex solution using Set object and custom getAllKeyNames() recursive function to get all unique key names from specified object:
var object1 = {"gender":"man","age":33,"origin":"USA","jobinfo":{"type":"teacher","school":"Wisconsin"},"children":[{"name":"Daniel","age":12,"pets":[{"type":"cat","name":"Willy","age":2},{"type":"dog","name":"jimmie","age":5}]},{"name":"Martin","age":14,"pets":[{"type":"bird","name":"wagner","age":12}]}],"hobbies":{"type":"football","sponsor":{"name":"Pepsi","sponsorAmount":1000,"contact":{"name":"Leon","age":59,"children":[{"name":"James","pets":[{"type":"dog","age":4}]}]}}}},
object2 = {"gender":"man","age":33,"origin":"USA","jobinfo":{"type":"teacher","school":"Wisconsin"},"children":[{"name":"Daniel","age":12,"pets":[{"type":"cat","name":"Willy","age":2},{"type":"dog","name":"jimmie","age":5}]}]};
function getAllKeyNames(o, res){
Object.keys(o).forEach(function(k){
if (Object.prototype.toString.call(o[k]) === "[object Object]") {
getAllKeyNames(o[k], res);
} else if (Array.isArray(o[k])) {
o[k].forEach(function(v){
getAllKeyNames(v, res);
});
}
res.add(k);
});
}
var o1Keys = new Set(), o2Keys = new Set();
getAllKeyNames(object1, o1Keys); // unique keys of object1
getAllKeyNames(object2, o2Keys); // unique keys of object2
// get a list of all the keys that are in object1, but not in object2
var diff = [...o1Keys].filter((x) => !o2Keys.has(x));
console.log(diff);
Thanks for the feedback.
I ended up solving it, with a lot of inspiration from Romans answer.
const compareObjects = (obj1, obj2) => {
function getAllKeyNames(o, arr, str){
Object.keys(o).forEach(function(k){
if (Object.prototype.toString.call(o[k]) === "[object Object]") {
getAllKeyNames(o[k], arr, (str + '.' + k));
} else if (Array.isArray(o[k])) {
o[k].forEach(function(v){
getAllKeyNames(v, arr, (str + '.' + k));
});
}
arr.push(str + '.' + k);
});
}
function diff(arr1, arr2) {
for(let i = 0; i < arr2.length; i++) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
return arr1;
}
const o1Keys = [];
const o2Keys = [];
getAllKeyNames(obj1, o1Keys, ''); // get the keys from schema
getAllKeyNames(obj2, o2Keys, ''); // get the keys from uploaded file
const missingProps = diff(o1Keys, o2Keys); // calculate differences
for(let i = 0; i < missingProps.length; i++) {
missingProps[i] = missingProps[i].replace('.', '');
}
return missingProps;
}
jsfiddle here: https://jsfiddle.net/p9Lm8b53/
You could use an object for counting.
function getCount(object, keys, inc) {
Object.keys(object).forEach(function (k) {
if (!Array.isArray(object)) {
keys[k] = (keys[k] || 0) + inc;
if (!keys[k]) {
delete keys[k];
}
}
if (object[k] && typeof object[k] === 'object') {
getCount(object[k], keys, inc)
}
});
}
var object1 = { gender: "man", age: 33, origin: "USA", jobinfo: { type: "teacher", school: "Wisconsin" }, children: [{ name: "Daniel", age: 12, pets: [{ type: "cat", name: "Willy", age: 2 }, { type: "dog", name: "jimmie", age: 5 }] }, { name: "Martin", age: 14, pets: [{ type: "bird", name: "wagner", age: 12 }] }], hobbies: { type: "football", sponsor: { name: "Pepsi", sponsorAmount: 1000, contact: { name: "Leon", age: 59, children: [{ name: "James", pets: [{ type: "dog", age: 4 }] }] } } } },
object2 = { gender: "man", jobinfo: { type: "teacher" }, children: [{ name: "Daniel", age: 12, pets: [{ type: "cat", name: "Willy", age: 2 }, { type: "dog", name: "jimmie", age: 5 }] }] },
count = {};
getCount(object1, count, 1);
getCount(object2, count, -1);
console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This recursive approach works best for me.
let object1 = {
a: 40,
b: 80,
c: 120,
xa: [
{
xc: 12,
xz: 12
}
],
rand: 12
};
let object2 = {
a: 20,
b: 30,
c: 40,
xa: [
{
xy: 12,
xz3: 12
}
]
};
function getObjDifferences(obj, obj2, propsMissing, keyName) {
Object.keys(obj).forEach(key => {
if(obj2[key] === undefined) {
if(keyName.length > 0) propsMissing.push(keyName+"->"+key);
else propsMissing.push(key)
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
if(obj2[key] !== undefined) {
if(keyName.length > 0) getObjDifferences(obj[key], obj2[key], propsMissing, keyName+"->"+key)
else getObjDifferences(obj[key], obj2[key], propsMissing, key)
} else {
propsMissing.push(key)
}
}
})
return propsMissing;
}
console.log(getObjDifferences(object1, object2, [], ''))
console.log(getObjDifferences(object2, object1, [], ''))

how to merge arrays which contains objects?

I have more than two arrays with objects which have some similar properties,
and I want to merge all arrays to one array and sort theme as bellow:
array = [
[ { "name" : "Jack", count: 10 }, { "name": "Fred", "count": 20 } ],
[ { "name": "Jack", count: 3 }, { "name": "Sara", "count": 10 } ]
]
merged_array = [
{ "name": "Fred", "count": 20 },
{ "name": "Jack", "count": 13 },
{ "name": "Sara", "count": 10 }
]
array
.reduce(function(result, arrayItem) {
result = result || [];
// sort also can be implemented here
// by using `Insertion sort` algorithm or anyone else
return result.concat(arrayItem);
})
.sort(function(a,b) { return a.count < b.count; })
You can use two forEach() to get array with merged objects and then sort it with sort().
var array = [
[{
"name": "Jack",
count: 10
}, {
"name": "Fred",
"count": 20
}],
[{
"name": "Jack",
count: 3
}, {
"name": "Sara",
"count": 10
}]
]
var result = [];
array.forEach(function(a) {
var that = this;
a.forEach(function(e) {
if (!that[e.name]) {
that[e.name] = e;
result.push(that[e.name]);
} else {
that[e.name].count += e.count
}
})
}, {})
result.sort(function(a, b) {
return b.count - a.count;
})
console.log(result)
If you are open to, then do take a look at to underscorejs, it is a wonderful utility for working with Arrays and objects as such. This will allow you to write flexible and transparent logic. The documentation is also quite good.
var arrays = [
[{
"name": "Jack",
count: 10
}, {
"name": "Fred",
"count": 20
}],
[{
"name": "Jack",
count: 3
}, {
"name": "Sara",
"count": 10
}]
]
var result = _.chain(arrays)
.flatten()
.union()
// whatever is the "key" which binds all your arrays
.groupBy('name')
.map(function(value, key) {
var sumOfCount = _.reduce(value, function(entry, val) {
// the fields which will need to be "aggregated"
return entry + val.count;
}, 0);
return {
'name': key,
'count': sumOfCount
};
}
)
// you can have your own sorting here
.sortBy('count')
.value();
console.log(result.reverse());
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Slice properties from objects and counting

Is it possible to slice single property from array of objects like
[{"name":"Bryan","id":016, "counter":0}, {"name":"John","id":04, "counter":2}, {"name":"Alicia","id":07, "counter":6}, {"name":"Jenny","id":015, "counter":9}, {"name":"Bryan","id":016, "counter":0}, {"name":"Jenny","id":015, "counter":9}, {"name":"John","id":04, "counter":2}, {"name":"Jenny" ,"id":015, "counter":9}];
I'm trying to slice name from every object and count number of the same elements (there are 3 objects with name Jenny) in order to achieve the following structure:
[{"name":"Bryan","Number":2},
{"name":"John","Number":2},
{"name":"Alicia","Number":1},
{"name":"Jenny","Number":3}]
Do you want to ignore the id and counter props already present?
You could create an object to keep track of the unique names, and convert back to an array in the end:
var data = [{"name": "Bryan", "id": 016, "counter": 0}, { "name": "John", "id": 04, "counter": 2}, { "name": "Alicia", "id": 07, "counter": 6}, { "name": "Jenny", "id": 015, "counter": 9}, { "name": "Bryan", "id": 016, "counter ": 0}, { "name": "Jenny", "id": 015, "counter ": 9}, { "name": "John", "id": 04, "counter": 2}, { "name": "Jenny", "id": 015, "counter": 9}];
var result = data.reduce(function(result, item) {
if (!result[item.name]) {
result[item.name] = {
name: item.name,
counter: 0
};
}
result[item.name].counter += 1;
return result;
}, {});
console.log(Object.keys(result).map(function(key) { return result[key] }));
You could use a hash table as a reference to the counted names.
var data = [{ name: "Bryan", id: "016", counter: 0 }, { name: "John", id: "04", counter: 2 }, { name: "Alicia", id: "07", counter: 6 }, { name: "Jenny", id: "015", counter: 9 }, { name: "Bryan", id: "016", counter: 0 }, { name: "Jenny", id: "015", counter: 9 }, { name: "John", id: "04", counter: 2 }, { name: "Jenny", id: "015", counter: 9 }],
grouped = [];
data.forEach(function (a) {
if (!this[a.name]) {
this[a.name] = { name: a.name, Number: 0 };
grouped.push(this[a.name]);
}
this[a.name].Number++;
}, Object.create(null));
console.log(grouped);
Give this a shot. We create a dictionary of names with their counts called nameDict, and iterate through the list to count them.
var arr = [{"name":"Bryan","id":"016", "counter":0}, {"name":"John","id":"04", "counter":2}, {"name":"Alicia","id":"07", "counter":6}, {"name":"Jenny","id":"015", "counter":9}, {"name":"Bryan","id":"016", "counter":0}, {"name":"Jenny","id":"015", "counter":9}, {"name":"John","id":"04", "counter":2}, {"name":"Jenny","id":"015", "counter":9}];
var nameDict = {};
for(var i = 0; i < arr.length; i++)
{
var name = arr[i].name;
if(nameDict[name] == undefined){
//haven't encountered this name before so we need to create a new entry in the dict
nameDict[name] = 1
} else {
//otherwise increment the count
nameDict[name] += 1
}
}
console.log(JSON.stringify(nameDict));

Categories

Resources