how to remove two json objects with same id - javascript

If I have a .json file with the following contents:
[
{
"id": "1234",
"day": "Monday",
"course": "Math110",
},
{
"id": "1234",
"day": "Wednesday",
"title": "Math110",
},
{
"id": "1345",
"day": "Tuesday",
"title": "Economics210",
}
]
How can I remove all the objects with id "1234" in Javascript? (note there are two objects with the same ID)
Would delete["1234"] work?

Use .filter to filter out elements of an array:
const input = [{
"id": "1234",
"day": "Monday",
"course": "Math110",
},
{
"id": "1234",
"day": "Wednesday",
"title": "Math110",
},
{
"id": "1345",
"day": "Tuesday",
"title": "Economics210",
}
];
const output = input.filter(({ id }) => id !== '1234');
console.log(output);

You cannot use delete operator because its for deleting a property in an object. You actually want to delete an object inside an array.
Use the good old for loop and Array.splice():
var inputArray = [{
"id": "1234",
"day": "Monday",
"course": "Math110",
},
{
"id": "1234",
"day": "Wednesday",
"title": "Math110",
},
{
"id": "1345",
"day": "Tuesday",
"title": "Economics210",
}
];
var deleteId = "1234";
for (var i = 0; i < inputArray.length; i++) {
if (inputArray[i].id === deleteId) {
inputArray.splice(i, 1);
i = i-1;
}
}
console.log(inputArray);
Note: If you are fine with creating another array and not modifying the existing array, use Array.filter() as mentioned in the other answers.

You can parse the JSON to an array and then use Array.prototype.filter to get a new array which doesn't have the objects with id "1234":
const json = '[{"id":"1234","day":"Monday","course":"Math110"},{"id":"1234","day":"Wednesday","title":"Math110"},{"id":"1345","day":"Tuesday","title":"Economics210"}]';
const result = JSON.parse( json ).filter( obj => obj.id !== "1234" );
console.log( JSON.stringify( result, null, ' '.repeat(8) ) );

You have to delete by specifying the position of the item in the array:
const arr = [{
"id": "1234",
"day": "Monday",
"course": "Math110",
},
{
"id": "1234",
"day": "Wednesday",
"title": "Math110",
},
{
"id": "1345",
"day": "Tuesday",
"title": "Economics210",
}
];
arr.forEach(function(item, i){
if(item.id == "1234")
delete arr[i];
});
console.log(arr.filter(j => j))

You can use filter method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
items = [
{
"id": "1234",
"day": "Monday",
"course": "Math110",
},
{
"id": "1234",
"day": "Wednesday",
"title": "Math110",
},
{
"id": "1345",
"day": "Tuesday",
"title": "Economics210",
}
];
items.filter(function(item) {
return item.id !== '1234';
});

Related

how to group the data by a field into subarray in JavaScript

I have an array like below. I want to group this array by day field.
input_array = [{
"name": "alagu",
"day": "monday",
"time": "morning",
"task": "studying"
}, {
"name": "alagu",
"day": "monday",
"time": "evening",
"task": "playing"
}, {
"name": "alagu",
"day": "monday",
"time": "night",
"task": "sleeping"
}, {
"name": "alagu",
"day": "sunday",
"time": "morning",
"task": "playing"
}, {
"name": "alagu",
"day": "sunday",
"time": "evening",
"task": "playing"
}, {
"name": "alagu",
"day": "sunday",
"time": "night",
"task": "sleeping"
}]
I want the result will be like the below array.
result_array = [{
"name": "alagu",
"day": "monday",
"schedule": [
{ "time": "morning", "task": "studying" },
{ "time": "evening", "task": "playing" },
{ "time": "evening", "task": "sleeping" }
]
}, {
"name": "alagu",
"day": "sunday",
"schedule": [
{ "time": "morning", "task": "playing" },
{ "time": "evening", "task": "playing" },
{ "time": "night", "task": "sleeping" }
]
}]
What I mean is I want to group by day and then I have to make sub array schedule having elements of time and task. please help.
For get your required result from sample data by foreach and map functions :
const input_array = [{ "name":"alagu", "day":"monday", "time":"morning", "task":"studying" },
{ "name":"alagu", "day":"monday", "time":"evening", "task":"playing" },
{ "name":"alagu", "day":"monday", "time":"night", "task":"sleeping" },
{ "name":"alagu", "day":"sunday", "time":"morning", "task":"playing" },
{ "name":"alagu", "day":"sunday", "time":"evening", "task":"playing" },
{ "name":"alagu", "day":"sunday", "time":"night", "task":"sleeping" }]
const result = {};
inputArray.forEach(item => {
const { name, day, time, task } = item;
if (!result[day]) {
result[day] = { name, day, schedule: [] };
}
result[day].schedule.push({ time, task });
});
const resultArray = Object.keys(result).map(key => result[key]);
console.log(resultArray);
Result :
[
{
"name":"alagu",
"day":"monday",
"schedule":[
{
"time":"morning",
"task":"studying"
},
{
"time":"evening",
"task":"playing"
},
{
"time":"night",
"task":"sleeping"
}
]
},
{
"name":"alagu",
"day":"sunday",
"schedule":[
{
"time":"morning",
"task":"playing"
},
{
"time":"evening",
"task":"playing"
},
{
"time":"night",
"task":"sleeping"
}
]
}
]
You can use reduce function like this:
const input_array = [{
"name": "alagu",
"day": "monday",
"time": "morning",
"task": "studying"
}, {
"name": "alagu",
"day": "monday",
"time": "evening",
"task": "playing"
}, {
"name": "alagu",
"day": "monday",
"time": "night",
"task": "sleeping"
}, {
"name": "alagu",
"day": "sunday",
"time": "morning",
"task": "playing"
}, {
"name": "alagu",
"day": "sunday",
"time": "evening",
"task": "playing"
}, {
"name": "alagu",
"day": "sunday",
"time": "night",
"task": "sleeping"
}]
const result_array = Object.entries(input_array.reduce((acc, curr) => {
return {
...acc,
[curr.day]: curr.day in acc ? [...acc[curr.day], curr] : [curr]
}
}, {})).map(([key, value]) => ({
name: value[0].name,
day: key,
schedule: value.map(val => ({
time: val.time,
task: val.task
}))
}))
console.log(result_array)
const data = [{"name":"alagu","day":"monday","time":"morning","task":"studying"},{"name":"alagu","day":"monday","time":"evening","task":"playing"},{"name":"alagu","day":"monday","time":"night","task":"sleeping"},{"name":"alagu","day":"sunday","time":"morning","task":"playing"},{"name":"alagu","day":"sunday","time":"evening","task":"playing"},{"name":"alagu","day":"sunday","time":"night","task":"sleeping"}]
let t, r = [...new Set(data.map(i=>i.day))]
.map(day=>(t=data.filter(i=>i.day===day),
{name: t[0].name, day, schedule: t.map(({name, day, ...o})=>o)}))
console.log(r)
I would personally introduce a general purpose groupBy() helper, that allows you to group a collection based on a key.
function groupBy(iterable, fn) {
const groups = new Map();
for (const item of iterable) {
const key = fn(item);
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push(item);
}
return groups;
}
With this helper defined we group the data using:
const groups = groupBy(input_array, item => JSON.stringify([item.name, item.day]));
The reason I use JSON.stringify() is because two arrays (objects) are only only equal to each other if they reference the same array. Therefore [item.name, item.day] will never match an existing key, since we just created the array instance. If we serialize the array (using JSON) we can compare 2 strings instead. Which are equal if they contain the same content.
// normal array comparison
["alagu", "monday"] === ["alagu", "monday"] //=> false
// serialized (using JSON) array comparison
'["alagu","monday"]' === '["alagu","monday"]' //=> true
After we've grouped the data, the groups structure looks like this:
// using object notation to display Map instance contents
Map{
'["alagu","monday"]': [
{ name: "alagu", day: "monday", time: "morning", task: "studying" },
{ name: "alagu", day: "monday", time: "evening", task: "playing" },
{ name: "alagu", day: "monday", time: "night" , task: "sleeping" },
],
'["alagu","sunday"]': [
{ name: "alagu", day: "sunday", time: "morning", task: "playing" },
{ name: "alagu", day: "sunday", time: "evening", task: "playing" },
{ name: "alagu", day: "sunday", time: "night" , task: "sleeping" },
],
}
We can then convert this into an array using Array.from(groups) and map() over the key/value pairs to transform them into the desired output.
const result_array = Array.from(groups).map(([json, items]) => {
const [name, day] = JSON.parse(json);
const schedule = items.map(({ time, task }) => ({ time, task }));
return { name, day, schedule };
});
const input_array = [
{ name: "alagu", day: "monday", time: "morning", task: "studying" },
{ name: "alagu", day: "monday", time: "evening", task: "playing" },
{ name: "alagu", day: "monday", time: "night" , task: "sleeping" },
{ name: "alagu", day: "sunday", time: "morning", task: "playing" },
{ name: "alagu", day: "sunday", time: "evening", task: "playing" },
{ name: "alagu", day: "sunday", time: "night" , task: "sleeping" },
];
const groups = groupBy(input_array, item => JSON.stringify([item.name, item.day]));
const result_array = Array.from(groups).map(([json, items]) => {
const [name, day] = JSON.parse(json);
const schedule = items.map(({ time, task }) => ({ time, task }));
return { name, day, schedule };
});
console.log(result_array);
// groupBy() helper
function groupBy(iterable, fn) {
const groups = new Map();
for (const item of iterable) {
const key = fn(item);
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push(item);
}
return groups;
}
In the above code we turn the serialized key back into a JavaScript structure using JSON.parse(), this allows us to grab the name and day of the current group.
We then need to transform items—an array of objects that still contain all the properties—into an array of objects that only have the time and task property.
.map(({ time, task }) => ({ time, task })) does exactly that. It is a combination of object destructuring and the property definition shorthand.

how to convert array into new array of parent children

I have restaurant data array , I should make another array by grouping items by category that belongs to , I should convert this array :
[
{
"category": {
"title": "Appetizers",
},
"id": 1,
"price": "10",
"title": "Spinach Artichoke Dip",
},
{
"category": {
"title": "Appetizers",
},
"id": 2,
"price": "10",
"title": "Hummus",
},
{
"category": {
"title": "Salads",
},
"id": 3,
"price": "7",
"title": "Greek",
},
{
"category": {
"title": "Salads",
},
"id": 4,
"price": "9",
"title": "Beyn",
}
]
into a new array that should be as final result like this:
[{
"category": "Appetizers",
"items" : ["Spinach Artichoke Dip","Hummus"]
},
{
"category" : "Salads",
"items" :["Greek", "Beyn"]
}
]
I can't find how to do it could you please help
Lets say that your data is a constant called data
So you can do this:
const data = [
{
"category": {
"title": "Appetizers",
},
"id": 1,
"price": "10",
"title": "Spinach Artichoke Dip",
},
{
"category": {
"title": "Appetizers",
},
"id": 2,
"price": "10",
"title": "Hummus",
},
{
"category": {
"title": "Salads",
},
"id": 3,
"price": "7",
"title": "Greek",
},
{
"category": {
"title": "Salads",
},
"id": 4,
"price": "9",
"title": "Beyn",
}
];
const result = [];
data.forEach((item) => {
const category = item.category.title;
const title = item.title;
let foundCategory = result.find((c) => c.category === category);
if (foundCategory) {
foundCategory.items.push(title);
} else {
result.push({ category, items: [title] });
}
});
console.log(result);
Now your desired result will be stored in result
happy coding
const itemsToCategories = (itemsArr) => {
const store = {};
itemsArr.forEach(item => {
const categoryTitle = item.category.title;
if (!store[categoryTitle]) store[categoryTitle] = [];
store[categoryTitle].push(item.title);
});
return Object.entries(store).map(([category, items]) => ({ category, items}));
};
This solution should be a bit faster than the accepted answer for large data sets. The main difference is the use of an object (store) instead of an array, so lookups by the category title are more efficient. Then we build an array from that object at the end.
This does have more overhead than the accepted solution above, so for smaller data sets, this ends up being slower in comparison.

How to merge two objects with same property in Node JS

I have a JSON Data like this:
"Data": [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
I want to merge two objects in this array, but it have same properties like date, dow
at the end I want to represent data like this:
"Data": [
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
]
time: should be least from both objects and endTime should be largest of both of them
count should be sum of both. date and dow is common in both objects
How can I merge these object in this way in node JS?
const data=[
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
let date=(time)=>new Date().setHours(...time.split(":"));
let newData=[];
data.forEach((item)=>{
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1){
let find=data.filter((e)=>e.dow===item.dow && e.date===item.date);
let time=find.filter((i)=>find.find(i2=>date(i2.time)>date(i.time)));
let endTime=find.filter((i)=>find.find(i2=>date(i2.endTime)<date(i.endTime)));
item.endTime=endTime?.[0]?.endTime || item?.endTime;
item.time=time?.[0]?.time || item?.time;
item.count=find.map((e)=>e.count).reduce((partialSum, a) => partialSum + a, 0);
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1) newData.splice(findItem,1);
newData.push(item);
}
else newData.push(item);
});
console.log(newData);
Here's a simple and readable answer:
const data = [
{
time: "18:40:43",
count: 7,
endTime: "15:46:25",
date: "2019-01-16",
dow: "Thursday",
},
{
count: 11,
time: "16:39:52",
endTime: "19:41:03",
dow: "Thursday",
date: "2019-01-16",
},
];
const mergeObjects = (data) => {
mergedObj = { ...data[0] };
for (i = 1; i < data.length; i++) {
const obj = data[i];
for (const key in obj) {
switch (key) {
case "count":
mergedObj.count = (mergedObj.count || 0) + obj.count;
case "time":
mergedObj.time =
mergedObj.time < obj.time ? mergeObjects.time : obj.time;
case "endTime":
mergedObj.endTime = mergedObj.endTime > obj.endTime ? mergeObjects.endTime : obj.endTime;
}
}
}
return mergedObj;
};
console.log(mergeObjects(data));
output
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
Assuming
"Data" would have only two objects inside it
time would be in "HH::MM::SS" format
Pass the values onto constructJSON utility function which would return the formatted value
var Data = [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
function constructJSON(data)
{
const returnData = {}
returnData['count'] = data[0].count + data[1].count
returnData['date'] = data[0].date // since its common for both
returnData['dow'] = data[0].dow // since its common for both
returnData['time'] = parseInt(data[0].time.split(':').join(''),10) < parseInt(data[1].time.split(':').join(''),10) ? data[0].time:data[1].time;
returnData['endTime'] = parseInt(data[0].endTime.split(':').join(''),10) > parseInt(data[1].endTime.split(':').join(''),10) ? data[0].endTime:data[1].endTime;
return returnData
}
console.log(constructJSON(Data))
If you use Array.reduce, you should be able to do this pretty easily, it should also expand to let you expand with more than just 2 objects in the array.
const data = [{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
//res will contain the output
const res = data.reduce(function(acc, curr) {
//Initially the accumulator will be null
if (!acc) return curr;
//Add the counts up
acc.count += curr.count;
//Convert both times into dates and find the minimum
const accTime = new Date(acc.date + 'T' + acc.time); //We add the T here since that's just how the Date constructor accepts times
const currTime = new Date(acc.date + 'T' + curr.time);
acc.time = new Date(Math.min(accTime, currTime)).toTimeString().split(' ')[0]; //See https://stackoverflow.com/questions/19346405/how-to-get-hhmmss-from-date-object
//Do the same for the end times but find the maximum
const accEndTime = new Date(acc.date + 'T' + acc.endTime);
const currEndTime = new Date(acc.date + 'T' + curr.endTime);
acc.endTime = new Date(Math.max(accEndTime, currEndTime)).toTimeString().split(' ')[0];
return acc;
});
console.log(res);
Another way of merging - all keys are combined, the common keys are overwritten by the second object, but count, time and endTime are calculated by special conditions
const
data = [{"time": "18:40:43","count": 7,"endTime": "15:46:25","date": "2019-01-16","dow": "Thursday"},{"count": 11,"time": "16:39:52","endTime": "19:41:03","dow": "Thursday","date": "2019-01-16"}],
[first, last] = data,
dumbDate = '2000-01-01 ',
result = {
...first,
...last,
count: first.count + last.count,
time: (new Date(`${dumbDate}${first.time}`) < new Date(`${dumbDate}${last.time}`)) ? first.time : last.time,
endTime: (new Date(`${dumbDate}${first.endTime}`) > new Date(`${dumbDate}${last.endTime}`)) ? first.endTime : last.endTime,
};
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}
Use Array#reduce() and Array#map() methods as follows:
const data = {"Data": [{"time": "18:40:43", "count": 7, "endTime": "15:46:25", "date": "2019-01-16", "dow": "Thursday"}, {"count": 11, "time": "16:39:52", "endTime": "19:41:03", "dow": "Thursday", "date": "2019-01-16" }]};
const newD = {Data:data.Data.reduce(
(prev,{date,dow,count,...r}) =>
//check if an element in array prev has dow & date props equal to the current element
prev.findIndex(p => p.date === date && p.dow === dow) > -1 ?
//If found process the matching element
prev.map(({date:d,dow:w,count:c,...rs}) =>
d === date && w === dow ?
({...rs,date:d,dow:w,count:c+count,time:rs.time < r.time ? rs.time : r.time,endTime:rs.endTime > r.endTime ? rs.endTime : r.endTime}) :
({...rs,date:d,dow:w,count:c})
) :
//If not add the current element to array prev
prev.concat({...r,date,dow,count}),
//start off with an empty array
[]
)};
console.log( newD );

Combining objects in array based on key values [duplicate]

This question already has answers here:
How to merge objects if certain keys and values match in JavaScript?
(4 answers)
Closed 2 years ago.
I have an array of objects with a common key. I would like to combine all the objects within the array based on key values.
My array:
let array = [
{
"day": "Monday",
"item1": "abc"
},
{
"day": "Tuesday",
"item1": "def"
},
{
"day": "Monday",
"item2": "123"
},
{
"day": "Tuesday",
"item2": "456"
}
]
Based on the example, I want to combine the objects within my array based on the common day key values and merge the rest of the other key value pairs (the rest of the keys are dynamic).
Expected output:
[
{
"day": "Monday",
"item1": "abc",
"item2": "123"
},
{
"day": "Tuesday",
"item1": "def",
"item2": "456"
}
]
I have tried using Lodash and plain ES6 but still unable to come up with a solution for it.
You can use lodash reduce function, like this:
let array = [
{
"day": "Monday",
"item1": "abc"
},
{
"day": "Tuesday",
"item1": "def"
},
{
"day": "Monday",
"item2": "123"
},
{
"day": "Tuesday",
"item2": "456"
}
]
let merged = _.reduce(array, function(result, value, key) {
let item = result.find(item => item.day === value.day);
if (!item) {
result.push(value)
} else {
_.merge(item, value);
}
return result;
} , []);
Try using Array#reduce , Spread Operator and approach with ES6
const arr = [ { "day": "Monday", "item1": "abc" }, { "day": "Tuesday", "item1": "def" }, { "day": "Monday", "item2": "123" }, { "day": "Tuesday", "item2": "456" } ];
let res = arr.reduce((acc,{day,...rem})=>( acc[day] = acc[day] ? {...acc[day],...rem} : {day,...rem},acc),{});
console.log(Object.values(res))
Found the solution
_(array).groupBy('day').map(_.spread(_.assign)).value()

How to generate different ObjectId's with MongoDB's positional operator $[]?

I want to update every element in the array days (I got 7 days, here I only show 3) with the MongoDB positional operator $[]. The update correctly pushes an object into every single element of the array meals. However, their Object Id's are the same, and I would like them to be different since I will be mapping them. Any ideas?
"_id": {
"$oid": "5db749cf657e1b1e0c3d241c"
},
"finished": false,
"days": [
{
"dayName": "Monday",
"meals": [
{
"_id": {
"$oid": "5dba1cde12f2b650e4b4f89d"
},
"mealName": "Breakfast",
"recipes": []
}
]
},
{
"dayName": "Tuesday",
"meals": [
{
"_id": {
"$oid": "5dba1cde12f2b650e4b4f89d"
},
"mealName": "Breakfast",
"recipes": []
}
]
},
{
"dayName": "Wednesday",
"meals": [
{
"_id": {
"$oid": "5dba1cde12f2b650e4b4f89d"
},
"mealName": "Breakfast",
"recipes": []
}
],
}
]
}

Categories

Resources