Retrieve value from object based on sub-value? - javascript

Say I have an object like so...
object = {
thing0:{
date: 'Sat, 05 May 2012 01:00:00 EST'
},
thing1:{
date: 'Sat, 05 May 2012 12:00:00 EST'
},
thing2:{
date: 'Fri, 04 May 2012 06:00:00 EST'
}
}
I want to retrieve the thing that has the latest date. How could I create a function to quickly compare and retrieve this value?

There's no shortcut, you'd need to do a for..in loop to loop over the property names, and check each thing's date.

How about:
obj = {
thing0:{
date: 'Sat, 05 May 2012 01:00:00 EST'
},
thing1:{
date: 'Sat, 05 May 2012 12:00:00 EST'
},
thing2:{
date: 'Fri, 04 May 2012 06:00:00 EST'
}
}
key_with_max_date = Object.keys(obj).map(function(k) {
return [new Date(obj[k].date), k];
}).sort().pop()[1]
Docs: Object.keys, Array.map

Related

How can I build an object in React(typescript) based on an array of objects

I have two user objects:
const user = {
startDate: new Date('2022-10-06'),
endDate: new Date('2022-10-10'),
id:'1234',
title: 'Title 1'
};
const user2 = {
startDate: new Date('2022-10-12'),
endDate: new Date('2022-10-17'),
id: '1112',
title: 'Title 2'
};
and an array with these two objects and an empty object called dateToUserMap:
const users = [user, user2];
const dateToUserMap = {};
I want to add data to dateToUserMap and it needs to look like this:
dateToUserMap = {
'01.11.2022': [
{
id: 'asd',
title: 'asd'
}
],
'02.11.2022': [
{
id: 'asd',
title: 'asd'
},
{
id: 'asd1',
title: 'asd1'
}
],
'03.11.2022': [
{
id: 'asd1',
title: 'asd1'
}
]
};
dateToUserMap should be an object with the days of the intervals of each user in chronological order (in my case should be days from 10/6 until 10/10 and 10/12 until 10/17), and each day should have an array of objects with the id and title of the users in that interval.
I tried using forEach to loop trough the users in the users array and calculated the interval of each user but I don't know how to pass that data in the object with all the dates and the id and title
users.forEach(user => {
const interval = eachDayOfInterval({ start: user.startDate, end: user.endDate });
console.log(interval);
});
I use date-fns library to help me work with dates and when I log the interval to console I get this:
(6) [Wed Oct 12 2022 00:00:00 GMT+0300 (Eastern European Summer Time), Thu Oct 13 2022 00:00:00 GMT+0300 (Eastern European Summer Time), Fri Oct 14 2022 00:00:00 GMT+0300 (Eastern European Summer Time), Sat Oct 15 2022 00:00:00 GMT+0300 (Eastern European Summer Time), Sun Oct 16 2022 00:00:00 GMT+0300 (Eastern European Summer Time), Mon Oct 17 2022 00:00:00 GMT+0300 (Eastern European Summer Time)]
0
:
Wed Oct 12 2022 00:00:00 GMT+0300 (Eastern European Summer Time) {}
1
:
Thu Oct 13 2022 00:00:00 GMT+0300 (Eastern European Summer Time)
[[Prototype]]
:
Object
2
:
Fri Oct 14 2022 00:00:00 GMT+0300 (Eastern European Summer Time) {}
3
:
Sat Oct 15 2022 00:00:00 GMT+0300 (Eastern European Summer Time) {}
4
:
Sun Oct 16 2022 00:00:00 GMT+0300 (Eastern European Summer Time) {}
5
:
Mon Oct 17 2022 00:00:00 GMT+0300 (Eastern European Summer Time) {}
length
:
6
[[Prototype]]
:
Array(0)

AlaSQL & ORDER BY clause with dates

I need to get my data ordered by date and events but I'm struggling to get it working using AlaSQL query on Date objects:
function testOrderBy() {
var data = [{event:'A', date: new Date('2021-04-21')},
{event:'B', date: new Date('2021-04-21')},
{event:'C', date: new Date('2021-04-21')},
{event:'D', date: new Date('2021-04-20')}];
console.log(data);
var res = alasql(`SELECT event, date FROM ? ORDER BY date, event`, [data]);
console.log(res);
}
And the result obtained is:
[ { event: 'D',
date: Tue Apr 20 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'C',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'B',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'A',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) } ]
I was expecting:
[ { event: 'D',
date: Tue Apr 20 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'A',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'B',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) },
{ event: 'C',
date: Wed Apr 21 2021 02:00:00 GMT+0200 (Central European Summer Time) } ]
The problem does not occur if dates are not Date objects but ISO strings:
function testOrderBy() {
var data = [{event:'A', date: '2021-04-21'},
{event:'B', date: '2021-04-21'},
{event:'C', date: '2021-04-21'},
{event:'D', date: '2021-04-20'}];
console.log(data);
var res = alasql(`SELECT event, date FROM ? ORDER BY date, event`, [data]);
console.log(res);
}
The result is as expected D, A, B, C
Any idea ?
It is necessary to create the table schema to correctly consider the column as a Date type, as follows:
alasql("CREATE TABLE events (event string, date date)");
alasql.tables.events.data = [{event:'A', date: new Date('2021-04-21')},
{event:'B', date: new Date('2021-04-21')},
{event:'C', date: new Date('2021-04-21')},
{event:'D', date: new Date('2021-04-20')}];
alasql(`SELECT event, date INTO HTML("#res") FROM events ORDER BY date, event`);
<script src="https://cdn.jsdelivr.net/npm/alasql#1.7.3/dist/alasql.min.js"></script>
<div id="res">
</div>

Reduce Object array with same values

I have an array of Javascript Objects, which contain two important values date and status
I want to reduce them into an array of unique dates, where all the values are parsed into an object, that contains each of the status and the date.
I have tried using the reduce funtion, but i can't seem to collect the dates properly, so that all the data is collected properly.
The unique statuses are: "System Labelled", "Discarded", "Saved", "Reviewed"
So for example:
[{status: "System Labelled", date: Thu Mar 05 2020 01:00:00 GMT+0100 (Central European Standard Time)},
{status: "System Labelled", date: Thu Mar 05 2020 01:00:00 GMT+0100 (Central European Standard Time)},
{status: "System Labelled", date: Thu Mar 05 2020 02:00:00 GMT+0200 (Central European Summer Time)},
{status: "Discarded", date: Tue Mar 10 2020 01:00:00 GMT+0100 (Central European Standard Time)},
{status: "Saved", date: Sat Jan 11 2020 01:00:00 GMT+0100 (Central European Standard Time)}]
---->
[{System Labelled: 1, Discarded: 0, Saved: 0, Reviwed: 0, date: Thu Mar 05 2020 01:00:00 GMT+0100 (Central European Standard Time)},
{System Labelled: 2, Discarded: 0, Saved: 0, Reviwed: 0, date: Sun Apr 05 2020 02:00:00 GMT+0200 (Central European Summer Time)},
{System Labelled: 0, Discarded: 1, Saved: 0, Reviwed: 0, date: Tue Mar 10 2020 01:00:00 GMT+0100 (Central European Standard Time)},
{System Labelled: 0, Discarded: 0, Saved: 1, Reviwed: 0, date: Sat Jan 11 2020 01:00:00 GMT+0100 (Central European Standard Time)},
Here is the code i have so far:
const objects= [{status: "System Labelled", date: new Date("19-03-2020")},
{status: "System Labelled", date: new Date("19-03-2020")},
{status: "Discarded", date: new Date("19-03-2020")},
{status: "Saved", date: new Date("19-03-2020")}]
objects.reduce((acc, curr) =>{
console.log(acc.includes(curr.status))
if(acc.includes(curr.status)){
curr[acc.status]++
}
},[])
You can take an object for grouping and get the values as result array.
You need valid dates for it.
const
statuses = ["System Labelled", "Discarded", "Saved", "Reviewed"],
objects = [{ status: "System Labelled", date: "2020-03-19" }, { status: "System Labelled", date: "2020-03-19" }, { status: "Discarded", date: "2020-03-19" }, { status: "Saved", date: "2020-03-19" }],
result = Object.values(objects.reduce((acc, { status, date }) => {
acc[date] = acc[date] || { date, ...Object.fromEntries(statuses.map(k => [k, 0])) };
acc[date][status]++;
return acc;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
what if you get the timestamp of each date and then add it as a string after the status it has to create one single string.
Example Object
[{status: "System Labelled", date: Thu Mar 05 2020 01:00:00 GMT+0100 (Central European Standard Time)}
Would Be
"System Labelled 1583366400"
And then you could just substring the timestamp to convert it to a date again

Sort array of objects with date field by date

Given the following array of objects, I need to ascending sort them by the date field.
var myArray = [
{
name: "Joe Blow",
date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "Sam Snead",
date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "John Smith",
date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}
];
In the above example, the final result would be John Smith, Sam Snead, and Joe Blow.
I am trying to use lodash's _.sortBy(), but I can't get any sorting to take place no matter how I try to use it:
_.sortBy(myArray, function(dateObj) {
return dateObj.date;
});
or
_.sortBy(myArray, 'date');
What do I need to change to get my array sorted properly? I also have Moment.js, so I can use it to format the date string if needed. I tried converting the date property using .unix(), but that didn't make a difference.
Thanks.
You don't really need lodash. You can use JavaScript's Array.prototype.sort method.
You'll need to create Date objects from your date strings before you can compare them.
var myArray = [{
name: "Joe Blow",
date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
}, {
name: "Sam Snead",
date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
}, {
name: "John Smith",
date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}];
myArray.sort(function compare(a, b) {
var dateA = new Date(a.date);
var dateB = new Date(b.date);
return dateA - dateB;
});
console.log(myArray);
Here's a solution using standard Javascript by converting both values to date object and comparing their value.
myArray.sort((d1, d2) => new Date(d1.date).getTime() - new Date(d2.date).getTime());
A complete snippet:
var myArray = [
{
name: "Joe Blow",
date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "Sam Snead",
date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "John Smith",
date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}
];
myArray.sort((d1, d2) => new Date(d1.date).getTime() - new Date(d2.date).getTime());
console.log(myArray);
Your date values are strings, so you need to use the new Date() constructor to change them to javascript date objects. This way you can sort them (using _.sortBy).
var myArray = [
{
name: "Joe Blow",
date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "Sam Snead",
date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "John Smith",
date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}
];
myArray = _.sortBy(myArray, function(dateObj) {
return new Date(dateObj.date);
});
console.log(myArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
If you are trying to use lodash to sort dates in ascending or descending order for your array of objects, you should use _.orderBy instead of _.sortBy
https://lodash.com/docs/4.17.15#orderBy, this method allows specifying sort orders either by 'asc' or 'desc'
An example would be:
const sortedArray = _(myArray.orderBy([
function(object) {
return new Date(object.date);
}],["desc"])
A cleaner way using Lodash orderBy:
import _ from 'lodash'
const sortedArray = _.orderBy(myArray, [(obj) => new Date(obj.date)], ['asc'])
just write _.sortBy({yourCollection}, {the field name});
lodash will automatically figure that this is a date and it'll work like a magic!
Awesome!
Inspired by others answers and noticing that you used moment.js and lodash, you can combine both with _.orderBy lodash method:
import moment from 'moment'
import * as _ from 'lodash'
let myArray = [
{
name: "Joe Blow",
date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "Sam Snead",
date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
},
{
name: "John Smith",
date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}
];
myArray = _.orderBy(myArray, [(item) => {
return moment(item.date).format('YYYY-MM-DD')
}], ['desc'])
this has worked for me
myArray = _.orderBy(myArray, [item => item.lastModified], ['desc']);

Amend results from two collections into an array using _.each()

My goal:
Call an API and inside this API I would like to:
Find Bills
Find all transactions under each bill (by billId)
Return the values in a JSON ARRAY
The bill array look like this:
{ _id: 549bf0597886c3763e000001,
billName: 'Leasing',
startDate: Thu Dec 25 2014 01:00:00 GMT+0100 (CET),
endDate: Sun Oct 15 2017 00:00:00 GMT+0200 (CEST),
amount: 16500,
type: 4,
timestamp: Thu Dec 25 2014 12:09:13 GMT+0100 (CET),
__v: 0 },
{ _id: 54a014bfac01ca3526000001,
billName: 'Test',
startDate: Tue Oct 28 2014 01:00:00 GMT+0100 (CET),
endDate: Wed Dec 20 2017 00:00:00 GMT+0100 (CET),
amount: 1000,
type: 4,
timestamp: Sun Dec 28 2014 15:33:35 GMT+0100 (CET),
__v: 0 }
From this array, which I get in the step 1, I would like to query the transactions collections and get each transaction for each bill.
The array would have the following transformation:
From:
{ _id: 549bf0597886c3763e000001,
billName: 'Leasing',
startDate: Thu Dec 25 2014 01:00:00 GMT+0100 (CET),
endDate: Sun Oct 15 2017 00:00:00 GMT+0200 (CEST),
amount: 16500,
type: 4,
timestamp: Thu Dec 25 2014 12:09:13 GMT+0100 (CET),
__v: 0 },
{ _id: 54a014bfac01ca3526000001,
billName: 'Test',
startDate: Tue Oct 28 2014 01:00:00 GMT+0100 (CET),
endDate: Wed Dec 20 2017 00:00:00 GMT+0100 (CET),
amount: 1000,
type: 4,
timestamp: Sun Dec 28 2014 15:33:35 GMT+0100 (CET),
__v: 0 }
To:
{ _id: 549bf0597886c3763e000001,
billName: 'Leasing',
startDate: Thu Dec 25 2014 01:00:00 GMT+0100 (CET),
endDate: Sun Oct 15 2017 00:00:00 GMT+0200 (CEST),
amount: 16500,
type: 4,
timestamp: Thu Dec 25 2014 12:09:13 GMT+0100 (CET),
__v: 0 ,
transactions: {
{
"_id" : ObjectId("549ea8c957b654ef64000003"),
"billId" : "5499aece1d7be6c6a3000001",
"paymentDate" : ISODate("2014-12-27T12:40:41.311+0000"),
"amount" : NumberInt(2400),
"timestamp" : ISODate("2014-12-27T12:40:41.311+0000"),
"__v" : NumberInt(0)
}
{
"_id" : ObjectId("549ea9446163b3c666000001"),
"billId" : "5499aece1d7be6c6a3000001",
"paymentDate" : ISODate("2014-12-27T12:42:44.975+0000"),
"amount" : NumberInt(2400),
"timestamp" : ISODate("2014-12-27T12:42:44.975+0000"),
"__v" : NumberInt(0)
}
}
},
{ _id: 54a014bfac01ca3526000001,
billName: 'Test',
startDate: Tue Oct 28 2014 01:00:00 GMT+0100 (CET),
endDate: Wed Dec 20 2017 00:00:00 GMT+0100 (CET),
amount: 1000,
type: 4,
timestamp: Sun Dec 28 2014 15:33:35 GMT+0100 (CET),
__v: 0 }
In my attempt, Im succeding until I get the bills ID from the bill collection but I cannot succeed to get the transaction IDs into an array.
My attempt looks like this:
app.get('/getbills', function(req,res) {
function getTransactions(item, key){
var billId = item._id;
Transactions.find({billId : billId}, function(err, transactions){ // TODO: Needs to look for transactions inside the date.
if (err)
console.log('error: '+ err)
else if (transactions.length !== 0){
return transactions;
}
});
};
Bills.find({type: bill_type}).find(function(err, bills){
if(err)
res.send(err);
details.bills = bills;
details.bills.transations = _.each(bills, getTransactions);
res.send(details);
});
});
I'm using _.each to hold the billId and query the transactions table but there are not enough examples explaining how to use this function in the way I'm trying. Or maybe my attempt is wrong.
Any help is welcome.
Thanks in advance.
You are not waiting for you second call to finish, so you don't have all data at hand. Your return statement does not work as you think it will.
You should read a bit about asynchronicity in JavaScript :)
This code should work. Please take some time to study it and understand why. The trySend function acts as a simple synchronizer and only responds when all data is available. This is not the best way to do it - only the simplest.
app.get('/bills', function( req, res ) {
Bills.find({type: bill_type}, function( err, bills ) {
if( err ) return res.send(err);
var tries = 0;
var details = { bills: bills };
var trySend = function (){
tries++;
if (tries === bills.length) {
res.send(details);
}
};
bills.forEach( function ( bill ) {
Transactions.find({billId : bill._id}, function ( err, transactions ) {
if ( err ) return res.send( err );
bill.transations = transactions;
trySend();
});
});
});
});

Categories

Resources