How to order by multiple date time properties with nulls last? - javascript

I have a json and I want to order this json by multiple date time properties. But there is a pinnedAt property which is pointing that post has to be on top. Im using lodash by the way.
This is the sql document of what I am trying to explain:
If NULLS LAST is specified, null values sort after all non-null values; if NULLS FIRST is specified, null values sort before all non-null values. If neither is specified, the default behavior is NULLS LAST when ASC is specified or implied, and NULLS FIRST when DESC is specified (thus, the default is to act as though nulls are larger than non-nulls). When USING is specified, the default nulls ordering depends on whether the operator is a less-than or greater-than operator.
You can read more here: https://www.postgresql.org/docs/9.0/static/sql-select.html
So here is my sample data:
{
"data": [
{
"name": "Paris",
"createdAt": "2018-10-01T08:28:05.074Z",
"pinnedAt": null
},
{
"name": "New York",
"createdAt": "2018-10-01T05:16:05.074Z",
"pinnedAt": null
},
{
"name": "Washington",
"createdAt": "2018-10-02T08:28:05.074Z",
"pinnedAt": "2018-10-02T15:19:23.245Z"
}
]
}
My code to order
posts = _.orderBy(state.posts, ['pinnedAt', 'createdAt'], ['desc', 'desc']);
But this doesn't order like what I want. Here is what I expected
{
"data": [
{
"name": "Washington",
"createdAt": "2018-10-02T08:28:05.074Z",
"pinnedAt": "2018-10-02T15:19:23.245Z"
},
{
"name": "Paris",
"createdAt": "2018-10-01T08:28:05.074Z",
"pinnedAt": null
},
{
"name": "New York",
"createdAt": "2018-10-01T05:16:05.074Z",
"pinnedAt": null
}
]
}
How can I do that?
Thank you.

You can use a custom function to treat null as a different value that will sort correctly.
const data = [
{
"name": "Paris",
"createdAt": "2018-10-01T08:28:05.074Z",
"pinnedAt": null
},
{
"name": "New York",
"createdAt": "2018-10-01T05:16:05.074Z",
"pinnedAt": null
},
{
"name": "Washington",
"createdAt": "2018-10-02T08:28:05.074Z",
"pinnedAt": "2018-10-02T15:19:23.245Z"
}
];
const result = _.orderBy(data,
[(item) => item.pinnedAt ? item.pinnedAt : "", 'createdAt'],
['desc', 'desc']);
Tested using version 4.17.11 of lodash using https://npm.runkit.com/lodash
This works because the empty string is "less than" any other string value. When sorting descending, this will always show up at the end of the list. Because these empty string values are equivalent, objects without pinnedAt will be sorted based on createdAt, as expected.

Related

Destructuring a json object in Javascript

How would access the _id and state values?
Here's the data
{
"data": {
"totalSamplesTested": "578841",
"totalConfirmedCases": 61307,
"totalActiveCases": 3627,
"discharged": 56557,
"death": 1123,
"states": [
{
"state": "Lagos",
"_id": "O3F8Nr2qg",
"confirmedCases": 20555,
"casesOnAdmission": 934,
"discharged": 19414,
"death": 207
},
{
"state": "FCT",
"_id": "QFlGp4md3y",
"confirmedCases": 5910,
"casesOnAdmission": 542,
"discharged": 5289,
"death": 79
}
]
}
}
What you have shown is a string in JSON format. You can convert that to a JavaScript object and then start to get the values you need from it.
let str = ‘{
"data": {
"totalSamplesTested": "578841",
"totalConfirmedCases": 61307,
"totalActiveCases": 3627,
"discharged": 56557,
"death": 1123,
"states": [
{
"state": "Lagos",
"_id": "O3F8Nr2qg",
"confirmedCases": 20555,
"casesOnAdmission": 934,
"discharged": 19414,
"death": 207
},
{
"state": "FCT",
"_id": "QFlGp4md3y",
"confirmedCases": 5910,
"casesOnAdmission": 542,
"discharged": 5289,
"death": 79
}
]
}
} ‘;
(Note, I have put the string in single quotes so it can be shown properly here but in your code you need to put it in back ticks so it can span many lines)
Now convert it to a JavaScript object.
let obj = JSON.parse(str);
Now look closely at the string to see how the object is structured. It actually has just one item in it, data. And that is itself an object with several items, one of which is states which is an array.
So, obj.data.states[0] is the array’s first entry. That is an object and has _id and state items.
You can step through the array extracting the ._id and .state entries.

How to get specific data from object array?

I'm a beginner and would like to know how I can get a specific object from an array
I have an Array that looks like this:
data {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
},
To get the data from above I would do something like this:
return this.data.orderid
But how can I go deeper and get the status in userinfo?
return this.data.orderid.userinfo.status
doesn't work... anyone have any ideas?
A few points:
data is not an array, is an Object (see the curly braces, arrays have squared brackets). To be really precise, your syntax is invalid, but I assume you wanted to type data = { ... }, as opposed to data { ... }
Your syntax is almost correct, the only mistake you are making is that userinfo is an array, and arrays have numeric indexes (I.e. array[0], array[1]). What you are looking for is this.data.orderid.userinfo[0].status
Use data.userinfo[0].status to get the value (in your case this.data.userinfo[0].status)
var data = {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
};
console.log(data.userinfo[0].status);
User Info is an array, so you would need to access it using indexer like so:
return this.data.userinfo[0].status
MDN on arrays: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
You need to iterate over data.userinfo (it's an array)
var data = {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
};
data.userinfo.forEach(function(element) {
console.log(element.status);
});

Iterating an Object using .map to display the inner array values

I have a JSON stringified object as:
{
"lesseeName": "Padyster-7",
"lesseeRegNo": "12345",
"lesseeVatNo": "4456",
"telFaxNo": "1234567891",
"billingAddress": {
"addressId": null,
"addressLine1": "XYz , l1 street",
"addressLine2": "near xyz bank",
"postalCode": "60000",
"countryName": "MY",
"cityName": "Kuala lumpur",
"stateProvinceCode": "Kuala lumpur"
},
"mlaList": [{
"mlaNo": 92,
"lesseeId": 108,
"executionDate": "27/01/2017",
"signatoryInfo": "Test",
"overdueRate": 3.44,
"nonPaymentDays": 2,
"consolidationTerm": "Monthly",
"createdBy": null,
"createdDtm": null,
"updatedBy": null,
"updatedDtm": null,
"statusIndicator": null,
"signatoryEmail": "tooot#gmail.com",
"leaseMlaNo": "OPM1",
"statusDescription": "APPROVED"
}, {
"mlaNo": 93,
"lesseeId": 108,
"executionDate": "03/01/2017",
"signatoryInfo": "tess",
"overdueRate": 5.77,
"nonPaymentDays": 2,
"consolidationTerm": "Bi-Monthly",
"createdBy": null,
"createdDtm": null,
"updatedBy": null,
"updatedDtm": null,
"statusIndicator": null,
"signatoryEmail": "xyz#gmail.com",
"leaseMlaNo": "OPM2",
"statusDescription": "APPROVED"
}]
}
I am working in Reactjs and I want my object to be iterated such that the inner array mlaList of objects gets iterated to display value one after other.
whenever I try using the .map function to the parent object I get an error saying ".map is not a function" below is the iteration I attempt which fails:
{data.map((data, index) => {data.leaseMlaNo} {data.signatoryEmail})}
I have referred to the SO questions quite similar to this one, but they just talk about iterating the objects using Object.keys
Please help me understand what I am doing wrong and what should be the correct way to achieve this
The method Array#map is a method of the Array class, and not of the Object class. However, the mlaList property is an array, and you can iterate it. You should use data.mlaList.map():
// if the data is stringified - const data = JSON.parse({ the object });
const data = {"lesseeName":"Padyster-7","lesseeRegNo":"12345","lesseeVatNo":"4456","telFaxNo":"1234567891","billingAddress":{"addressId":null,"addressLine1":"XYz , l1 street","addressLine2":"near xyz bank","postalCode":"60000","countryName":"MY","cityName":"Kuala lumpur","stateProvinceCode":"Kuala lumpur"},"mlaList":[{"mlaNo":92,"lesseeId":108,"executionDate":"27/01/2017","signatoryInfo":"Test","overdueRate":3.44,"nonPaymentDays":2,"consolidationTerm":"Monthly","createdBy":null,"createdDtm":null,"updatedBy":null,"updatedDtm":null,"statusIndicator":null,"signatoryEmail":"tooot#gmail.com","leaseMlaNo":"OPM1","statusDescription":"APPROVED"},{"mlaNo":93,"lesseeId":108,"executionDate":"03/01/2017","signatoryInfo":"tess","overdueRate":5.77,"nonPaymentDays":2,"consolidationTerm":"Bi-Monthly","createdBy":null,"createdDtm":null,"updatedBy":null,"updatedDtm":null,"statusIndicator":null,"signatoryEmail":"xyz#gmail.com","leaseMlaNo":"OPM2","statusDescription":"APPROVED"}]};
const result = data.mlaList.map((o, index) => o.signatoryEmail); // in react <div key={index}>{o.signatoryEmail}</div> for example
console.log(result);
array.prototype.map is an array function, not for objects so you would want to call it on your mlalist key:
const data = {"lesseeName":"Padyster-7","lesseeRegNo":"12345","lesseeVatNo":"4456","telFaxNo":"1234567891","billingAddress":{"addressId":null,"addressLine1":"XYz , l1 street","addressLine2":"near xyz bank","postalCode":"60000","countryName":"MY","cityName":"Kuala lumpur","stateProvinceCode":"Kuala lumpur"},"mlaList":[{"mlaNo":92,"lesseeId":108,"executionDate":"27/01/2017","signatoryInfo":"Test","overdueRate":3.44,"nonPaymentDays":2,"consolidationTerm":"Monthly","createdBy":null,"createdDtm":null,"updatedBy":null,"updatedDtm":null,"statusIndicator":null,"signatoryEmail":"tooot#gmail.com","leaseMlaNo":"OPM1","statusDescription":"APPROVED"},{"mlaNo":93,"lesseeId":108,"executionDate":"03/01/2017","signatoryInfo":"tess","overdueRate":5.77,"nonPaymentDays":2,"consolidationTerm":"Bi-Monthly","createdBy":null,"createdDtm":null,"updatedBy":null,"updatedDtm":null,"statusIndicator":null,"signatoryEmail":"xyz#gmail.com","leaseMlaNo":"OPM2","statusDescription":"APPROVED"}]};
const list = data.mlaList.map(val => `${val.leaseMlaNo} ${val.signatoryEmail}`);
console.log(list)

Indexing array values in an object in an IndexedDB

For a Chrome app, wich stores data in IndexedDB, i have a object like this:
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"parcels": [
{
"service": "DHL",
"track": "12345"
},
{
"service": "UPS",
"track": "3254231514"
}
]
}
If i store the hole object in an objectStore, can i use an index for "track", which can be contained multiple times in each order object?
Or is it needed or possibly better/faster to split each object into multiple objectStores like know from relational DBs:
order
orderitem
parcel
The solution should also work in a fast way with 100.000 or more objects stored.
Answering my own question: I have made some tests now. It looks like it is not possible to do this with that object in only 1 objectStore.
An other example object which would work:
var myObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"shipping": {"method": "letter",
"company": "Deutsche Post AG" }
}
Creating an index will be done by:
objectStore.createIndex(objectIndexName, objectKeypath, optionalObjectParameters);
With setting objectKeypath it is possible to address a value in the main object like "name":
objectStore.createIndex("name", "name", {unique: false});
It would also be possible to address a value form a subobject of an object like "shipping.method":
objectStore.createIndex("shipping", "shipping.method", {unique: false});
BUT it is not possible to address values like the ones of "track", which are contained in objects, stored in an array. Even something like "parcels[0].track" to get the first value as index does not work.
Anyhow, it would be possible to index all simple elements of an array (but not objects).
So the following more simple structure would allow to create an index entry for each parcelnumber in the array "trackingNumbers":
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"trackingNumbers": ["12345", "3254231514"]
}
when creating the index with multiEntry set to true:
objectStore.createIndex("tracking", "trackingNumbers", {unique: false, multiEntry: true});
Anyhow, the missing of the possibility to index object values in arrays, makes using indexedDB really unneeded complicated. It's a failure in design. This forces the developer to do things like in relational DBs, while lacking all the possibilities of SQL. Really bad :(

How to change the order of a JavaScript object?

My JavaScript object looks like this:
"ivrItems": {
"50b5e7bec90a6f4e19000001": {
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
"50b5e7c3c90a6f4e19000002": {
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
},
"50b5e7c8c90a6f4e19000003": {
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
}
}
Now I want to change the order of the object dynamically.
After sorting, the object should look as follows:
"ivrItems": {
"50b5e7bec90a6f4e19000001": {
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
"50b5e7c8c90a6f4e19000003": {
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
}
"50b5e7c3c90a6f4e19000002": {
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
}
}
Is there any possible way to do this?
To get and then change the order of an Object's enumeration, you need to manually define the order. This is normally done by adding the properties of the object to an Array.
var keys = Object.keys(data.ivrItems);
Now you can iterate the keys Array, and use the keys to access members of your irvItems object.
keys.forEach(function(key) {
console.log(data.irvItems[key]);
});
Now the order will always be that of the order given by Object.keys, but there's no guarantee that the order will be what you want.
You can take that Array and reorder it using whatever ordering you need.
keys.sort(function(a, b) {
return +data.irvItems[a].key - +data.irvItems[b].key;
});
This sort will sort the keys by the nested key property of each object after numeric conversion.
You should use an Array. Object keys has no order
like this:
{
"ivrItems": [
{
"id": "50b5e7bec90a6f4e19000001",
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
{
"id": "50b5e7c8c90a6f4e19000003",
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
},
{
"id": "50b5e7c3c90a6f4e19000002",
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
}
]
}
You're probably going to have a tough time with cross-browser compatibility, if you're doing this in the browser. But computers are mostly deterministic, so you could probably accomplish this reliably in one javascript engine implementation, though. For example, in the Chrome REPL / console, you can get this order simply by sequencing adding the properties:
var n = {}
n.b = 2
n.c = 3
var m = {}
m.c = 3
m.b = 2
JSON.stringify(n)
> "{"b":2,"c":3}"
JSON.stringify(m)
> "{"c":3,"b":2}"
So you could reconstruct your object, adding the keys in the order you want to find them later.
But the other people are right, if you want true, predictable order, you should use an array.
Javascript objects are intrinsically unordered.
You can't do that.

Categories

Resources