JavaScript merge array objects with the same keys - javascript

I have an array with several objects some have the same keys (Question and QuestionId), for example:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 }] },
{
Question: "Was the training useful?",
QuestionId: 1 ,
myData: [{ name: 'Yes', value: 1 }]
}];
How can I combine these objects into one, expected output:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 },
{ name: 'Yes', value: 1 }]
}];

var jsonData = [{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{
name: 'No',
value: 1
}]
},
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{
name: 'Yes',
value: 1
}]
}
];
const result = Object.values(jsonData.reduce((acc, obj) => {
if (!acc[obj.QuestionId]) {
acc[obj.QuestionId] = obj;
} else {
acc[obj.QuestionId].myData = acc[obj.QuestionId].myData ?? []; // if myData is null or undefined, set it to an empty array
acc[obj.QuestionId].myData = acc[obj.QuestionId].myData.concat(obj.myData);
}
return acc;
}, {}));
console.log(result);

function mergeData(data) {
const acc = {}
data.forEach(x => {
const id = x.QuestionId
if (!acc[id]) acc[id] = x
else acc[id].myData = acc[id].myData.concat(x.myData)
})
return Object.values(acc)
}

You can use forEach to create an object where the keys are the question IDs and then use Object.values to get the values into an array.
var jsonData = [{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 }]
}, {
Question: "Was the training useful?",
QuestionId: 1 ,
myData: [{ name: 'Yes', value: 1 }]
}];
var temp = {};
jsonData.forEach(x=>{
if(!temp[x.QuestionId]) {temp[x.QuestionId] = x;}
else {temp[x.QuestionId].myData.push(x.myData);}
});
var arr = Object.values(temp);
console.log(arr);

Related

How filter array of objects based on objects exists in another array of objects?

I have
array1 = [{ name: sample1 }, { name: sample2 }, { name: sample3 }];
array2 = [{ name: sample1 }, { name: sample2 }];
I want to filter objects of array1 which exists in array2.
So I need to have
[{ name: sample1 }, { name: sample2 }]
How can I get it in javascript?
You can use .filter and .some function in JavaScript ,
Here is the example
const array1 = [{ name: "sample1" }, { name: "sample2" }, {
name: "sample3" }];
const array2 = [{ name: "sample1" }, { name: "sample2" }];
let Result = array1.filter(function(obj) {
return array2.some(function(obj2) {
return obj.name== obj2.name;
});
});
console.log(Result)
You can use object destructuring, the map() and .includes() methods as shown below:
const array1 = [{ name: "sample1" }, { name: "sample2" }, { name: "sample3" }];
const array2 = [{ name: "sample1" }, { name: "sample2" }];
const filtered = array1.filter(
({name}) => array2.map(o => o.name).includes(name)
);
console.log( filtered );

I am trying to retrieve result from 2 array

i am trying to filter first array based on second array text , but i am not getting how to update the count filter to the first array from second array.
First Array:
var firstArray =[{text:"India",count:1,checked:true},
{text:"America",count:2,checked:false},
{text:"Uk",count:1,checked:true}];
Second Array:
var secondArray=[
{text:"India",count:1,checked:false},
{text:"America",count:1,checked:false},
{text:"Uk",count:1,checked:false}
];
Code:
var result=firstArray.filter(o1 => secondArray.some(o2 => o1.text === o2.text));
Result which i am currently getting:
var result=[
{text:"India",count:1,checked:true},
{text:"America",count:2,checked:false},
{text:"Uk",count:1,checked:true}
];
Result which i am trying to get is below:
var result=[
{text:"India",count:1,checked:true},
{text:"America",count:1,checked:false},
{text:"Uk",count:1,checked:true}
];
Thanks for the help!!!
You can map the first array and pick the count from second array like this
var firstArray = [
{ text: "India", count: 1, checked: true },
{ text: "America", count: 2, checked: false },
{ text: "Uk", count: 1, checked: true },
];
var secondArray = [
{ text: "India", count: 1, checked: false },
{ text: "America", count: 1, checked: false },
{ text: "Uk", count: 1, checked: false },
];
firstArray
.map((x) => {
const tmp = secondArray.find((y) => y.text === x.text);
return tmp ? { ...x, count: tmp.count } : null
})
.filter(Boolean);
A possible solution would like as below
var firstArray = [{
text: "India",
count: 1,
checked: true
},
{
text: "America",
count: 2,
checked: false
},
{
text: "Uk",
count: 1,
checked: true
}
];
var secondArray = [{
text: "India",
count: 1,
checked: false
},
{
text: "America",
count: 1,
checked: false
},
{
text: "Uk",
count: 1,
checked: false
}
];
var result = firstArray.map(o1 => {
const o2 = secondArray.find(o2 => o1.text === o2.text);
if (!o2) return;
return { ...o1,
count: o2.count
}
}).filter(o1 => !!o1);
console.log(result)
This solution will merge the two arrays to get the desidered result (as deduced from the answer)
var firstArray =[{text:"India",count:1,checked:true},
{text:"America",count:2,checked:false},
{text:"Uk",count:1,checked:true}];
var secondArray=[
{text:"India",count:1,checked:false},
{text:"America",count:1,checked:false},
{text:"Uk",count:1,checked:false}
];
const newArray = firstArray.map((el1) => {
let sameElList = secondArray.filter((el2) => el2.text === el1.text);
let sameEl = sameElList.length > 0 && sameElList.pop();
if(!sameEl){
return el1;
}
el1.count = Math.min(el1.count, sameEl.count);
el1.checked = el1.checked || sameEl.checked;
return el1;
});
console.log(newArray);

How to compare two array with object?

I compare id with two array with object.
Here is my function:
array1 = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
];
array2 = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
];
const compareFunction = (array1, array2) => {
array2.map((allValue) => {
array1.map((value) => {
allValue.selected = value.id === allValue.id;
});
})
return array2;
}
I think I will get the array2 like
[{ id: 1, selected: true }, { id: 2, selected: true },{ id: 3, selected: true }]
but actually array2 become
[{ id: 1, selected: false }, { id: 2, selected: false },{ id: 3, selected: true }]
Only the last array argument selected become true.
Which step was wrong ? Thanks.
Convert the 2nd array to a Set of id values. Iterate the 1st array with a Array.map() and create a new object for each item, by spreading the current object, and adding the selected value. To get the selected value check if the Set contains that current item id.
const array1 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const array2 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const a2Set = new Set(array2.map(o => o.id))
const result = array1.map(o => ({ ...o, selected: a2Set.has(o.id) }))
console.log(result)
checkout this :
array1 = [{ id: 1 },{ id: 2 },{ id: 3 }];
array2 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const compareFunction = (array1, array2) => {
const result = [];
array2.forEach(arr2item => {
let selected = false;
for(let arr1item of array1){
selected = arr1item.id === arr2item.id;
if(selected)break;
}
result.push({id : arr2item.id , selected : selected});
});
return result;
}
console.log(compareFunction(array1 , array2));

How to traverse through 2 javascript array of objects and create a third one?

I have two objects. obj2 has texts and obj1 has 3 subIbjId. How can I add the 'id' to obj2 based on obj1?
For example: obj1 has 2 subObjId in the first object(1001, 1002). I want to count the number of subObjId obj1 has and iterate through obj1 and add the key and value of id for the to obj2. If obj1 has two subObjId, then add id: 1 to the first two entries of obj2 and so on.
I am learning javascript and trying to solve some imaginary problems. Any help would be greatly appreciated. Thank you.
var obj1 = { [
{
id: 1,
name: ‘apple’,
subObjId: [ 1001, 1002]
subObjs: [
{
subId: 1001
subName: ‘ant’,
},
{
subId: 1002
subName: ‘ball’,
}
],
},
{
{
id: 2,
name: ‘zebra’,
subObjId: [ 1003]
subObjs: [
{
subId: 1003
subName: ‘cat’,
}
],
},
]
}
var obj2 = { [
{
text: ‘i am a text’
},
{
text: ‘i am some random characters’
},
{
text: ‘i am some numbers’
}
] }
to become
finalObject = { [
{
id: 1,
text: ‘i am a text’
},
{
id: 1,
text: ‘i am some random characters’
},
{
id: 2,
text: ‘i am some numbers’
}
] }
Try this!!
var obj1 = [
{
id: 1,
name: 'apple',
subObjId: [ 1001, 1002]
},
{
id: 2,
name: 'zebra',
subObjId: [ 1003]
}
]
var obj2 = [
{
text: 'i am a text'
},
{
text: 'i am some random characters'
},
{
text: ' am some numbers'
}
]
let index = 0;
let start = 0;
obj1.map(data1=>{
index += data1.subObjId.length;
for(var i=start;i<index;i++){
obj2[i]['id'] = data1.id;
}
start = i;
})
console.log(obj2)
You can use
Array#flatMap to extract an array of all subObjs items
also Array#map them into their parent's id property only.
Perform another mapping operation that copies the contents of a matching object in obj2 and adds an id.
For convenience, this uses the second argument to Array#map, which sets the this context inside the callback.
Also uses destructuring for compactness and spread syntax for making copies:
var obj1 = [ { id: 1, name: 'apple', subObjId: [1001, 1002], subObjs: [ { subId: 1001, subName: 'ant' }, { subId: 1002, subName: 'ball' } ] }, { id: 2, name: 'zebra', subObjId: [1003], subObjs: [ { subId: 1003, subName: 'cat', } ], }, ];
var obj2 = [ { text: 'i am a text' }, { text: 'i am some random characters' }, { text: 'i am some numbers' } ];
var finalObject = obj1
//1. flatMap into a single array
.flatMap(({id, subObjs}) => subObjs
.map(sub => ({id})) //take only the parent ID for each sub object
)// result: [{id: 1}, {id: 1}, {id: 2}]
.map(function({id}, index) {
return { id, ...this[index] } //2. create a new object with the id and the content of a matching object from the other array
}, obj2);// <- set the `this` context for the callback
console.log(finalObject);
It can also be done as a single operation when flatmapping by setting the this context to a copy of the second array (to avoid mutating obj2), then taking items off the front of the new array with Array#shift:
var obj1 = [ { id: 1, name: 'apple', subObjId: [1001, 1002], subObjs: [ { subId: 1001, subName: 'ant' }, { subId: 1002, subName: 'ball' } ] }, { id: 2, name: 'zebra', subObjId: [1003], subObjs: [ { subId: 1003, subName: 'cat', } ], }, ];
var obj2 = [ { text: 'i am a text' }, { text: 'i am some random characters' }, { text: 'i am some numbers' } ];
var finalObject = obj1.flatMap(function({id, subObjs}) {
return subObjs.map(sub => ({ id, ...this.shift() }))
}, [...obj2]);// <- copy obj2 as the `this` context
console.log(finalObject);
Use this snippet
var obj1 = [
{
id: 1,
name: 'apple',
subObjId: [1001, 1002],
subObjs: [{
subId: 1001,
subName: 'ant',
},
{
subId: 1002,
subName: 'ball',
}
],
},
{
id: 2,
name: 'zebra',
subObjId: [1003],
subObjs: [{
subId: 1003,
subName: 'cat',
}],
},
]
var obj2 = [
{
text: 'i am a text'
},
{
text: 'i am some random characters'
},
{
text: 'i am some numbers'
}
]
var finalObject = obj1.map(function (value, index) {
return {
id: value.id,
text: obj2[index].text
}
})
console.log(finalObject)

Flatten 3D array containing objects to 2D removing duplicated objects by it's parameter

I have a 3D array with objects inside:
[
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
]
How to flatten it including removing duplicated id parameter?
[{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
I think underscore would be helpful with that
var a = [
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
];
var flattened = _(a).flatten().uniq('id').value();
Of course you have to include lodash to your webpage.
You can use Underscore flatten and unique to accomplish this. However, whenever you are using multiple underscore operations, it is a good time to consider using the underscore chainging with chain and value:
var data = [
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
];
var result = _.chain(data)
.flatten()
.uniq(function(o) {
return o.id;
})
.value();
console.log('result', result);
JSFiddle: http://jsfiddle.net/0udLde0s/3/
Even shorter with current Underscore.js
If you use a recent version of Underscore.js (I tried current which is 1.8.3 right now), you can use .uniq('id') so it makes it even shorter:
var result = _.chain(data)
.flatten()
.uniq('id')
.value();
You can use _.flatten, and _.uniq, like so
var data = [
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
];
var result = _.uniq(_.flatten(data), function (el) {
return el.id;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
You don't need any library for this, it's quite simple:
function flatten(arr)
{
var map = {};
var flatArray = [];
function pushToMap(o) {
if(map[o.id])
return;
map[o.id] = true;
flatArray.push(o);
}
function arrRecurse(a) {
if(a.length === undefined)
pushToMap(a);
else {
a.forEach(function(i) {
arrRecurse(i);
});
}
}
arrRecurse(arr);
return flatArray;
}
var _3dArray = [
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
];
alert(JSON.stringify(flatten(_3dArray)));
No library, only native JS :
var ar = [
[{ id: 1 }, { id: 2 }],
[{ id: 3 }],
[{ id: 3 }, { id: 4 }]
];
//start
var output = [];
for (var x = 0, al = {}; x < ar.length; x++)
for (var y = 0, t = ar[x][y]; y < ar[x].length; y++, t = ar[x][y])
al[t.id] = (!al[t.id]) ? output.push(t) : 1;
//end
document.body.innerHTML += JSON.stringify(output);

Categories

Resources