Group arrays inside of an array - javascript

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
// }
// }

Related

How to filter from an object by iterating over it in js

I am trying to get the value of "type" from the object by iterating over it. The object looks like this.
{
"team": {
"table": [
{
"cityCode": 123,
"list": {
"players": [
{
"name": "peter",
"school": "x",
"awards": {
"type": "gold"
},
"year": 2019
}
]
}
},
{
"cityCode": 456,
"list": {
"players": [
{
"name": "Dave",
"school": "y",
"awards": {
"type": "silver"
},
"year": 2018
}
]
}
}
]
}
}
I am able to get the type values using this:
const table = team.table;
for (let i = 0; i < table.length; i++) {
const values = {
type: table[i].list.players
.filter((a) => a.awards != null)
.map((a) => a.awards.type)
.join(" "),
};
}
However, I want to use another filter on the "list" to filter non null lists. So how can I achieve that.
You want to check Check if 'list' key exists inside a team.table JSON object
you can check by
if(table[i].hasOwnProperty('list')){
}
code is
const table = team.table;
for (let i = 0; i < table.length; i++) {
if(table[i].hasOwnProperty('list')){
const values = {
type: table[i].list.players
.filter((a) => a.awards != null)
.map((a) => a.awards.type)
.join(" "),
};
}
}
1) You can get all type using flatMap and map as:
obj.team.table.flatMap((o) => o.list.players.map((o) => o.awards.type))
const obj = {
team: {
table: [
{
cityCode: 123,
list: {
players: [
{
name: "peter",
school: "x",
awards: {
type: "gold",
},
year: 2019,
},
],
},
},
{
cityCode: 456,
list: {
players: [
{
name: "Dave",
school: "y",
awards: {
type: "silver",
},
year: 2018,
},
],
},
},
],
},
};
const types = obj.team.table.flatMap((o) => o.list.players.map((o) => o.awards.type));
console.log(types);
2) Using forEach and destructuring as:
const obj = {
team: {
table: [
{
cityCode: 123,
list: {
players: [
{
name: "peter",
school: "x",
awards: {
type: "gold",
},
year: 2019,
},
],
},
},
{
cityCode: 456,
list: {
players: [
{
name: "Dave",
school: "y",
awards: {
type: "silver",
},
year: 2018,
},
],
},
},
],
},
};
const table = obj.team.table;
const types = [];
for (let i = 0; i < table.length; i++) {
const { list: { players } } = table[i]
players.forEach(({ awards: { type }}) => types.push(type))
}
console.log(types);
It will be cleaner to use forEach.
You will need 2 forEach due to your data structure.
But below code will:
check if awards is null
check if awards.type is null
const data = {
"team": {
"table": [
{
"cityCode": 123,
"list": {
"players": [
{
"name": "peter",
"school": "x",
"awards": {
"type": "gold"
},
"year": 2019
}
]
}
},
{
"cityCode": 456,
"list": {
"players": [
{
"name": "Dave",
"school": "y",
"awards": {
"type": "silver"
},
"year": 2018
},
{
"name": "Dave",
"school": "y",
"awards": {
"type": "gold"
},
"year": 2016
}
]
}
},
{
"cityCode": 444,
"list": {
"players": [
{
"name": "James",
"school": "y",
"awards": {
"type": null
},
"year": 2016
}
]
}
},
{
"cityCode": 555,
"list": {
"players": [
{
"name": "Name 101",
"school": "y",
"awards": {
"type": "platinum"
},
"year": 2016
},
{
"name": "Name 102",
"school": "y",
"awards": {
"type": null
},
"year": 2016
},
{
"name": "Name 103",
"school": "y",
"awards": null,
"year": 2016
},
]
}
}
]
}
}
// Expanded your data with more items
const data1 = data.team.table;
let types = []
data1.forEach((item, index) => {
item.list.players.forEach((player) => {
const awards = player.awards;
if (awards !== null && awards.type !== null) {
types = [...types, awards.type];
}
})
})
// Get the list of types
console.log(types);
// Get unique list of types
let unique_types = [...new Set(types)]
console.log(unique_types);

Convert object of objects of key value to array of object of same key value and return the after each iteration

I am trying to convert object with object inside to array of objects.
I have the data as:
"data" :{
"tDetails": {
"tName": "Limited",
"tPay": " xyz",
},
"bDetails": {
"bName": "name",
"bid": "bid",
"bNo": "123456",
},
"iDetails": {
"iName": "iname",
"iBranch": "ibranch",
},
}
i want to convert it to array of objects with each iteration over the three headers(tDetails, iDetails,bDetails) as:
const newData = [
{
"id": 1,
"title": "tDetails",
"content": [
{
"id": 1,
"key": "tName",
"value": "Limited"
},
{
"id": 2,
"key": "tPay",
"value": "xyz"
}
]
},
{
"id": 2,
"title": "bDetails",
"content": [
{
"id": 1,
"key": "bId",
"value": "12345"
}
]
},
{
"id": 3,
"title": "iDetails",
"content": [
{
"id": 1,
"key": "iName",
"value": "iname"
},{
"id":2,
"key": "iBranch",
"value": "ibranch"
}
]
},
]
const NewData = () => {
let newDetails = [];
let newHeader = '';
for (const header in data) {
// header here is 'tDetails', bDetails, iDetails
const headerData = data[header];
newDetails = Object.entries(headerData).map(([key, value]) => ({
key,
value,
}));
newHeader = header;
}
return [
{
title: newHeader,
content: newDetails,
},
];
};
This returns me the data of only the last part(iDetails) as it is returned after the for loop.What should be changed here
Map the object's entries instead of using for..in, and in the callback, return the transformed object.
const data={tDetails:{tName:"Limited",tPay:" xyz"},bDetails:{bName:"name",bid:"bid",bNo:"123456"},iDetails:{iName:"iname",iBranch:"ibranch"}};
const newData = Object.entries(data).map(([title, obj], i) => ({
title,
id: i + 1,
content: Object.entries(obj).map(([key, value], j) => ({
id: j + 1,
key,
value
}))
}));
console.log(newData);

Handle Array of Object manipulation

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.

Create new javascript object from 2 JSON objects grouped by id

I have below dynamic nested JSON object arrays and I wanted to get the desired output with JavaScript grouped by id from both.
First Array:
[
{
"id": "11",
"name": "emp1",
"location": [
{ "name": "abc", "id": "lc1" }
]
},
{
"id": "11",
"name": "emp2",
"location": [
{ "name": "abc", "id": "lc1" },
]
},
{
"id": "22",
"name": "emp3",
"location": [
{ "name": "xyz", "id": "lc2" }
]
}
]
Second array like below.
[
{
"name": "sub1",
"id": "11"
...
},
{
"name": "sub1.1",
"id": "11"
...
},
{
"name": "sub2",
"id": "22"
...
}
]
Desired Output:
[
{
"id": "11",
"first": [{"name": "emp1"},
{"name": "emp2"}],
"second": [{"name": "sub1"},{"name": "sub1.1"}],
"location": [{"name": "abc"}]
},
{
"id": "22",
"first": [{"name": "emp3"}],
"second": [{"name": "sub2"}],
"location": [{"name": "xyz"}]
}
]
How to get the desired output like above using javascript/angularjs?
I would do it using the amazing Array#reduce function.
Note that I have named your first array as a1, second as a2 and result as res.
a1.reduce(function(arr, obj) {
var existing = arr.filter(function(res) {
return res.id === obj.id
})[0]
if (existing) {
existing.first.push({
name: obj.name
})
} else {
var second = a2.filter(function(res) {
return res.id === obj.id
})
var secondObj = second.length ? second.map(function(sec) {
return {
name: sec.name
};
}) : []
arr.push({
id: obj.id,
first: [{
name: obj.name
}],
second: secondObj,
location: obj.location
})
}
return arr;
}, [])
Here's the working snippet. Take a look!
var a1 = [{
"id": "11",
"name": "emp1",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "11",
"name": "emp2",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "22",
"name": "emp3",
"location": [{
"name": "xyz",
"id": "lc2"
}]
}
]
var a2 = [{
"name": "sub1",
"id": "11"
}, {
"name": "sub1.1",
"id": "11"
},
{
"name": "sub2",
"id": "22"
}
]
var res = a1.reduce(function(arr, obj) {
var existing = arr.filter(function(res) {
return res.id === obj.id
})[0]
if (existing) {
existing.first.push({
name: obj.name
})
} else {
var second = a2.filter(function(res) {
return res.id === obj.id
})
var secondObj = second.length ? second.map(function(sec) {
return {
name: sec.name
};
}) : []
arr.push({
id: obj.id,
first: [{
name: obj.name
}],
second: secondObj,
location: obj.location
})
}
return arr;
}, [])
console.log(res)
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
var red1 = [{
"id": "11",
"name": "emp1",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "11",
"name": "emp2",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "22",
"name": "emp3",
"location": [{
"name": "xyz",
"id": "lc2"
}]
}
]
var b = [{
"name": "sub1",
"id": "11"
},
{
"name": "sub2",
"id": "22"
}
]
var identication = {}
var result = []
red1.forEach(function(val) {
if (val['id'] in identication) {
var t = {}
t['name'] = val['name']
result[identication[val['id']]]['first'].push(t)
} else {
var t = {}
t['name'] = val['name']
val['first'] = []
val['first'].push(t)
delete val['name']
var identity = result.push(val)
identication[val['id']] = identity - 1;
}
})
b.forEach(function(d) {
if (d['id'] in identication) {
var t = {
'name': d['name']
}
if (!('second' in result[identication[d['id']]])) {
result[identication[d['id']]]['second'] = []
}
result[identication[d['id']]]['second'].push(t)
} else {
var t = {}
for (key in d) {
if (key == 'name')
continue
t[key] = d[key]
}
t['second'] = [{
'name': d['name']
}]
var identity = result.push(t)
identication[d['id']] = identity - 1;
}
})
console.log(result)

Replace js code with aggregate in mongodb

I have mongo document called groups. This is array of students and subjects.
Each subject has an array of lessons.
Each lesson has an array of marks.
Generally, document looks like this:
[
{
"students": [
{ "_id": "0", "firstName": "Bob", "lastName": "Jhonson" },
{ "_id": "1", "firstName": "Jackie", "lastName": "Chan" }
// other students ...
],
"subjects": [
{
"name": "Algebra",
"lessons": [
{
"date": 1489363200,
"marks": [
{ "student_id": "0", "value": 5 },
{ "student_id": "1", "value": 4 }
// other marks...
]
}, {
"date": 1489622400,
"marks": [
{ "student_id": "0", "value": 3 },
{ "student_id": "1", "value": 2 }
// other marks...
]
}
// other lessons...
]
}
]
}
]
Then I use js function to transform this data to something like this:
[
{
"_id": "5a89ca11abc4ffd25a430420",
"subjects": [
{
"name": "Algebra",
"dates": [1489363200, 1489622400],
"students": [
{
"_id": "0",
"firstName": "Bob",
"lastName": "Jhonson",
"marks": [ 5, 3 ]
},
{
"_id": "1",
"firstName": "Jackie",
"lastName": "Chan",
"marks": [ 4, 2 ]
}
]
}
]
}
]
Function which transforms json document:
function transformData (groups) { // groups - array
let newGroups = [];
for (let group of groups) {
newGroup = {};
for (let key in group) {
if (key === 'students' || key === 'subjects') continue;
newGroup[key] = group[key];
}
newGroup.subjects = [];
for (let subject of group.subjects) {
let newSubject = {
name: subject.name,
dates: [],
students: []
};
for (let student of group.students) {
let index = newSubject.students.push(student) - 1;
newSubject.students[index].marks = [];
}
for (let lesson of subject.lessons) {
let index = newSubject.dates.push(lesson.date) - 1;
for (let mark of lesson.marks) {
for (let student of newSubject.students) {
if (student._id !== mark.student_id) continue;
while(student.marks.length !== index) {
student.marks.push(null);
}
student.marks.push(mark.value);
}
}
}
newGroup.subjects.push(newSubject);
}
newGroups.push(newGroup);
}
return newGroups;
}
How can I replace this function with mongodb aggregation?

Categories

Resources