Handle Array of Object manipulation - javascript

Below I have an array of objects
var data = [{
"time": "1572024707.4763825",
"rssi": "32",
"id": "77777"
}, {
"time": "1572024709.0991757",
"rssi": "32",
"id": "77777"
}, {
"time": "1572024704.4570136",
"rssi": "32",
"id": "555555"
}, {
"time": "1572024708.3903246",
"rssi": "32",
"id": "77777"
}, {
"time": "1572024699.7132683",
"rssi": "32",
"id": "66666"
}]
How can I restructure it to remove the repeating id's with the oldest time
I tried to pull all the unique IDs from the array so I can loop through the data array but then the code started to get too long.
data.forEach(item => {
IDs.push(item.id);
});
var unqIDs = [...new Set(IDs)];
console.log(unqIDs);
the output should look like this
outPutShouldBe = [{
"time": "1572024699.7132683",
"rssi": "32",
"id": "66666"
},{
"time": "1572024709.0991757",
"rssi": "32",
"id": "77777"
}, {"time": "1572024704.4570136",
"rssi": "32",
"id": "555555"
}
]

Create an object mapping ids to the item w/ the earliest time of those with that id:
var keydata = {};
data.forEach(item=>{
var p = keydata[item.id];
if ( !p || p.time>item.time ) {
keydata[item.id] = item;
}});
Now gather up the values in that object:
var newdata = [];
for ( var k in keydata ) {
newdata.push(keydata[k]);
}
or the more elegant (thanks, #TulioF.):
var newdata = Object.values(keydata)

Using forEach() find() filter() and filter() to decide which element to return
var data = [{"time": "1572024707.4763825","rssi": "32","id": "77777"},{"time": "1572024709.0991757","rssi": "32","id": "77777"}, {"time": "1572024704.4570136","rssi": "32","id": "555555"}, {"time": "1572024708.3903246","rssi": "32","id": "77777"}, {"time": "1572024699.7132683","rssi": "32","id": "66666"}]
let resultsArray = []
data.forEach(obj=>{
const foundObj = resultsArray.find(data => data.id === obj.id)
if(foundObj && new Date(foundObj.time) > new Date(obj.time)){
const filteredArray = resultsArray.filter(data => data.id === obj.id)
resultsArray = [...filteredArray , foundObj]
} else if (!foundObj){
resultsArray.push(obj)
}
})
console.log(resultsArray)

You coud take an object as hash table and get the values directly.
var data = [{ time: "1572024707.4763825", rssi: "32", id: "77777" }, { time: "1572024709.0991757", rssi: "32", id: "77777" }, { time: "1572024704.4570136", rssi: "32", id: "555555" }, { time: "1572024708.3903246", rssi: "32", id: "77777" }, { time: "1572024699.7132683", rssi: "32", id: "66666" }],
result = Object.values(data.reduce((r, o) => {
if (!r[o.id] || +r[o.id].time > +o.time) r[o.id] = o;
return r;
}, {}));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

use lodash to sort the array in descending order or ascending order as per your need (desc, asc) and get the zeroth object. try something like this. filter and orderBy
var data = [{
"time": "1572024707.4763825",
"rssi": "32",
"id": "77777"
}, ....];
let idsSet = new Set();
data.map(item=> idsSet.add(item.id));
let idsArr = Array.from(idsSet);
let newArr = [];
idsArr.map(id=>{
let tempArray = data.filter(item => item.id === id);
return newArr.push((_.orderBy(tempArray, ['time'],['desc']))[0]);
} )
console.log(newArr);
console output
[ {
"time": "1572024709.0991757",
"rssi": "32",
"id": "77777"
}, {
"time": "1572024704.4570136",
"rssi": "32",
"id": "555555"
}, {
"time": "1572024699.7132683",
"rssi": "32",
"id": "66666"
}];

Here you can do something like this :
let existMap = {};
data.filter(val => {
if((val.id in existMap) && (val.time>existMap[val.id])) return;
else{
existMap[val.id] = val.time;
return true;
}
})
console.log(result)
The condition can be changed based on requirement. just want to reference for your problem.

Related

Is there a way to compare dates and store them in an array?

I'm currently working on a website where Objects are sorted. The Objects are from a database where it's stored with a date (2022-10-13 02:07:11). Is there a way to compare dates and store the ones that are created on the same date? For example: If there are two objects that were created on 2022-10-13, but with at a different time, I would like to save these in an array with the name of the date.
I can't change how it's saved because it's not my DB.
I hope you understand how I mean it.
(I don't know how you want it or how your database is exactly so you might have to change some things)
Try using (something like) this:
let sorted = {};
// replace "data" below with your key
for(key in data){
if(!sorted[data[key].date]){
sorted[data[key].date] = [];
}
sorted[data[key].date].push({key: data[key]});
}
Example in my case:
let data = {
"a": {
"date": "2022-10-13 02:07:11"
},
"b": {
"date": "2022-10-13 00:00:00"
},
"c": {
"date": "2022-10-10 02:07:11"
}
};
let sorted = {};
for (key in data) {
if (!sorted[data[key].date]) {
sorted[data[key].date] = [];
}
sorted[data[key].date].push({
key: data[key]
});
}
console.log(sorted);
A reduce is useful here
Give us more details of the object to give a more tailored answer
const obj = [
{ "id": "a1", "date": "2022-10-13 01:07:11" },
{ "id": "a2", "date": "2022-10-13 02:07:11" },
{ "id": "a3", "date": "2022-10-13 03:07:11" },
{ "id": "b", "date": "2022-10-14 02:07:11" },
{ "id": "c1", "date": "2022-10-15 01:07:11" },
{ "id": "c2", "date": "2022-10-15 02:07:11" },
{ "id": "c3", "date": "2022-10-15 03:07:11" },
{ "id": "d", "date": "2022-10-16 01:07:11" }
];
const grouped = obj.reduce((acc,cur) => {
const key = cur.date.split(" ")[0];
(acc[key] = acc[key] || []).push(cur);
return acc;
},{})
console.log(grouped);

Group arrays inside of an array

I'm trying to group a list by an ID then inside that new list I'm trying to group a list of values based on that id in a certain time. I've manged to group by the id. I can't figure out what I need to do to group by the duration. Any help please
const data = [
{
"name": "ted",
"id": "1",
"timestamp": 1512709024000
},
{
"name": "seth",
"id": "2",
"timestamp": 1512754631000
},
{
"name": "joe",
"id": "1",
"timestamp": 1512711000000
},
{
"name": "phil",
"id": "2",
"timestamp": 1512754583000
},
{
"name": "kane",
"id": "1",
"timestamp": 1512709065294
},
]
}
{
"result": {
"1": [
{
"duration":18273
"names": ["ted", "joe", "kane"],
"startTime": 1512709065294
}
]
}
}
my efforts so far
const d= data;
const ids= data.reduce((ids, item) => {
const id= (ids[item.id] || [])
id.push(item);
ids[item.id] = id
return ids
}, {})
console.log('visitorIds',visitorIds)
Check this out:
const data = [
{"name": "ted","id": "1","timestamp": 1512709024000},
{"name": "seth","id": "2","timestamp": 1512754631000},
{"name": "joe","id": "1","timestamp": 1512711000000},
{"name": "phil","id": "2","timestamp": 1512754583000},
{"name": "kane","id": "1","timestamp": 1512709065294},
];
const visitors = (data) => {
const groupedData = data.reduce((acc, {id, name, timestamp}) => {
acc[id] = (acc[id])
? {...acc[id], names: [...acc[id].names, name], times: [...acc[id].times, timestamp]}
: {names: [name], times: [timestamp]};
const startTime = Math.min(...acc[id].times);
const finishTime = Math.max(...acc[id].times);
const duration = finishTime - startTime;
acc[id] = {...acc[id], duration, startTime};
return acc;
}, {});
Object.values(groupedData).forEach((obj) => delete obj.times);
return groupedData;
};
console.log(visitors(data));
// {
// '1': {
// names: [ 'ted', 'joe', 'kane' ],
// duration: 1976000,
// startTime: 1512709024000
// },
// '2': {
// names: [ 'seth', 'phil' ],
// duration: 48000,
// startTime: 1512754583000
// }
// }

Object.assign nested array with only certain properties

I have json data from below. The goal is to take all the Orders and combine them into one array while maintaining the Amount and the IdNumber so that I can use lodash _.groupBy on the Type.
In the end I'll have, for example, Type: test with each IdNumber and the Order Amounts that correspond to that IdNumber
I tried Object.assign on the data and did
data.forEach(d => {
let orders = d['Orders'];
let newOrders = Object.assign({}, {Idnumber: data.IdNumber, Orders: orders});
let groupedOrders = _.groupBy(newOrders, 'Type');
});
But, I'm not sure how to get just the Amount and Type of orders and merge them into one array. I'm also unclear if Object.assign is keeping track of the IdNumber with the Orders. when going through the array. I've never used Object.assign so perhaps that isn't even the right method to go about what I need.
Json data:
data = [
{
"Name": "abc",
"Amount": 3000,
"Idnumber": "001",
"Date": "11/17/2017",
"Orders": [
{
"Order Number": "11",
"Date": "11/18/2017",
"Amount": 1000,
"Type": "test"
},
{
"Order Number": "12",
"Date": "12/31/2017",
"Amount": 2000,
"Type": "trial"
}
],
"foo": "foo",
"foo2": foo,
"foo3": "foo",
"foo4": "foo"
},
{
"Name": "def",
"Amount": 5000,
"Idnumber": "002",
"Date": "12/15/2017",
"Orders": [
{
"Order Number": "10",
"Date": "11/02/2017",
"Amount": 7600,
"Type": "trial"
},
{
"Order Number": "16",
"Date": "05/31/2018",
"Amount": 15000,
"Type": "interim"
}
],
"foo": "foo",
"foo2": foo,
"foo3": "foo",
"foo4": "foo"
}
]
You can use array#reduce and array#map to inject Idnumber to each order and later on use array#reduce to group data based on the Type.
const data = [{"Name":"abc","Amount":3000,"Idnumber":"001","Date":"11/17/2017","Orders":[{"Order Number":"11","Date":"11/18/2017","Amount":1000,"Type":"test"},{"Order Number":"12","Date":"12/31/2017","Amount":2000,"Type":"trial"}],"foo":"foo","foo2":"foo","foo3":"foo","foo4":"foo"},{"Name":"def","Amount":5000,"Idnumber":"002","Date":"12/15/2017","Orders":[{"Order Number":"10","Date":"11/02/2017","Amount":7600,"Type":"trial"},{"Order Number":"16","Date":"05/31/2018","Amount":15000,"Type":"interim"}],"foo":"foo","foo2":"foo","foo3":"foo","foo4":"foo"}];
var result = data.reduce((r, {Orders, Idnumber}) => {
let orders = Orders.map(order => Object.assign({}, order, {Idnumber}));
return r.concat(orders);
},[]);
console.log(result);
console.log('--------------Grouped By----------');
var groupedBy = result.reduce((r,o) => {
r[o.Type] = r[o.Type] || [];
r[o.Type].push(o)
return r;
},{});
console.log(groupedBy);
.as-console-wrapper { max-height: 100% !important; top: 0; }
newOrder = data.map(d => ({Orders: d.Orders, idNumber: d.Idnumber}))

mapping JSON Data reverse?

I got stuck on a maybe simple task, but could not find any solution.
I have some JSON Data - lets say:
[{
"_id": 1,
"type": "person",
"Name": "Hans",
"WorksFor": ["3", "4"]
}, {
"_id": 2,
"type": "person",
"Name": "Michael",
"WorksFor": ["3"]
}, {
"_id": 3,
"type": "department",
"Name": "Marketing"
}, {
"_id": 4,
"type": "department",
"Name": "Sales"
}]
As I learned here it is quite simple to get all the persons and the departments they work for together using a map array for the departments.
Then I can map the corresponding department to the Person and receive something like:
[{
"_id": 1,
"type": "person",
"Name": "Hans",
"WorksFor": ["3", "4"],
"Readable": ["Marketing", "Sales"]
}, {
"_id": 2,
"type": "person",
"Name": "Michael",
"WorksFor": ["3"],
"Readable": ["Sales"]
}]
But for another interface I need the data "the other way round" e.g.
[{
"_id": 3,
"type": "department",
"Name": "Marketing",
"employees": [
"Hans", "Michael"
]
}, {
"_id": 4,
"type": "department",
"Name": "Sales",
"employees": [
"Hans"
]
}]
Is there any decent way to achieve this structure? Two days of trying didn't get me anywhere...
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"] }, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"] }, { "_id": 3, "type": "department", "Name": "Marketing" }, { "_id": 4, "type": "department", "Name": "Sales" }];
var departments = [],
persons = [];
data.forEach(e => {
if (e.type === "person") {
persons.push(e);
} else if (e.type === "department") {
departments.push(e);
e.employees = [];
}
});
departments.forEach(d => {
var workers = persons.filter(p => p.WorksFor.indexOf(d._id.toString()) > -1)
/*.map(p => p.Name)*/ // add this if you only need the name instead of the complete "person"
d.employees = d.employees.concat(workers);
});
console.log(JSON.stringify(departments, null, 4));
You can try something like this:
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}]
var ignoreDept = ['person'];
var result = data.reduce(function(p,c,i,a){
if(ignoreDept.indexOf(c.type) < 0){
c.employees = a.reduce(function(arr,emp){
if(emp.WorksFor && emp.WorksFor.indexOf(c._id.toString()) > -1){
arr.push(emp.Name)
}
return arr;
},[]);
p.push(c);
}
return p;
}, []);
console.log(result)
The solution using Array.prototype.filter() and Array.prototype.forEach() functions:
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}],
// getting separated "lists" of departments and employees(persons)
deps = data.filter(function(o){ return o.type === "department"; }),
persons = data.filter(function(o){ return o.type === "person"; });
deps.forEach(function (d) {
d['employees'] = d['employees'] || [];
persons.forEach(function (p) {
if (p.WorksFor.indexOf(String(d._id)) !== -1) { // check the `id` coincidence between the employee and the department
d['employees'].push(p.Name);
}
});
});
console.log(deps);
You could use a hash table and a single loop for each array.
Methods:
Array#reduce for iterating an array and returning the result,
Array#forEach for looping the inner array WorksFor,
Object.create(null) to generate an object without any prototypes,
some other pattern, like a closure over hash and
the use of logical OR || for checking a falsy value and taking an object as default.
hash[b] = hash[b] || { _id: b, employees: [] };
var data = [{ _id: 1, type: "person", Name: "Hans", WorksFor: [3, 4] }, { _id: 2, type: "person", Name: "Michael", WorksFor: [3] }, { _id: 3, type: "department", Name: "Marketing" }, { _id: 4, type: "department", Name: "Sales" }],
result = data.reduce(function (hash) {
return function (r, a) {
if (a.type === 'person') {
a.WorksFor.forEach(function (b) {
hash[b] = hash[b] || { _id: b, employees: [] };
hash[b].employees.push(a.Name);
});
}
if (a.type === 'department') {
hash[a._id] = hash[a._id] || { _id: b, employees: [] };
hash[a._id].type = a.type;
hash[a._id].Name = a.Name;
r.push(hash[a._id]);
}
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's a way you can get the first mapping. I've added some comments so you can follow along, and with it I hope you can find the answer to your second problem.
// First, let's get just the items in this array that identify persons
// I've called this array "data"
data.filter(x => x.type === 'person')
// Now let's map over them
.map(person =>
// We want all of the data associated with this person, so let's
// use Object.assign to duplicate that data for us
Object.assign({}, person, {
// In addition, we want to map the ID of the WorksFor array to the Name
// of the corresponding department. Assuming that the _id key is unique,
// we can due this simply by mapping over the WorksFor array and finding
// those values within the original array.
Readable: person.WorksFor.map(wfId =>
// Notice here the parseInt. This will not work without it due to
// the type difference between WorksFor (string) and _id (integer)
data.find(d => d._id === parseInt(wfId)).Name
)
})
);
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}];
var dep = {};
data.forEach(e => (e.type === 'person' && e.WorksFor.forEach(d => dep[d]? dep[d].push(e.Name): dep[d] = [e.Name])));
data.forEach(e => (e.type == 'department' && (e.employees = dep[e._id] || [])));
data = data.filter(e => e.type == 'department');
console.log(data);

Json object formatting with a groupby

I am trying to format a json object by groupping city name. I am trying to take a separate array and move the items based on found and not found to build a string. I am using javascript/angularjs to achieve this.
My current string
CurrentDataFormat =
[
{"Id":17,"code":"123","cityName":"Los Angeles","startDate":"1/20/2016","endDate":"1/20/2016"},
{"Id":18,"code":"456","cityName":"Chicago ","startDate":"1/22/2016","endDate":"1/25/2016"},
{"Id":19,"code":"789","cityName":"Los Angeles","startDate":"1/13/2016","endDate":"1/21/2016"}
]
I am trying to achieve this format
ExpectedDataFormat =
[{
"name":"Los Angeles",
"CityData":
[
{"Id":"17","code":"123","startDate":"1/20/2016","endDate":"1/20/2016"},
{"Id":"19","code":"789","startDate":"1/13/2016","endDate":"1/21/2016"}
]},{
"name":"Chicago",
"CityData":
[
{"Id":"18","code":"456","startDate":"1/22/2016","endDate":"1/25/2016"},
]}
}
Logic What am I trying (trying with different data though)
var array = [
{ "name": "project1", "url": "picture1-1.jpg"},
{ "name": "project1", "url": "picture1-2.jpg"},
{ "name": "project2", "url": "picture2-1.jpg"},
{ "name": "project3", "url": "picture3-1.jpg"},
{ "name": "project1", "url": "picture1-3.jpg"},
{ "name": "project4", "url": "picture4-1.jpg"},
{ "name": "project3", "url": "picture3-2.jpg"},
{ "name": "project1", "url": "picture1-4.jpg"}
];
var separateArray = [];
$.each(array, function (i, item) {
var foundItem = false;
$.each(separateArray, function (y, newItem) {
if (newItem.name == item.name) {
if (!(newItem.url instanceof Array)) {
newItem.url = [newItem.url];
}
newItem.url.push(item.url);
foundItem = true;
}
});
if (!foundItem) {
separateArray.push(item);
}
});
console.log(separateArray);
Would this code do what you need ?
var newarray = [];
CurrentDataFormat.forEach(function(item){
if(newarray[item.cityName] != undefined){
var key = item.cityName;
delete item.cityName;
newarray[key].CityData.push(item);
}else{
var o = {};
o.name = item.cityName;
o.CityData = [];
o.CityData.push(item);
newarray[o.name] = o;
}
});
console.log(newarray);
Check following code,
CurrentDataFormat = [{
"Id": 17,
"code": "123",
"cityName": "Los Angeles",
"startDate": "1/20/2016",
"endDate": "1/20/2016"
},
{
"Id": 18,
"code": "456",
"cityName": "Chicago",
"startDate": "1/22/2016",
"endDate": "1/25/2016"
},
{
"Id": 19,
"code": "789",
"cityName": "Los Angeles",
"startDate": "1/13/2016",
"endDate": "1/21/2016"
}
]
var refinedArray = {};
for (i = 0; i < CurrentDataFormat.length; i++) {
refinedArray[CurrentDataFormat[i].cityName] = refinedArray[CurrentDataFormat[i].cityName] ? refinedArray[CurrentDataFormat[i].cityName] : {};
refinedArray[CurrentDataFormat[i].cityName].name = CurrentDataFormat[i].cityName;
refinedArray[CurrentDataFormat[i].cityName].CityData = refinedArray[CurrentDataFormat[i].cityName].CityData ? refinedArray[CurrentDataFormat[i].cityName].CityData : [];
refinedArray[CurrentDataFormat[i].cityName].CityData.push({
"Id": CurrentDataFormat[i].Id,
"code": CurrentDataFormat[i].code,
"startDate": CurrentDataFormat[i].startDate,
"endDate": CurrentDataFormat[i].endDate
});
}
var ExpectedDataFormat = [];
for (singleCityName in refinedArray){
ExpectedDataFormat.push({'name' : refinedArray[singleCityName].name, 'CityData' : refinedArray[singleCityName].CityData});
};
ExpectedDataFormat is holding your desired output
Working demo at jsFiddle

Categories

Resources