Willie
Willie

Reputation: 338

Sorting Array of Objects by Object Name Typescript

Using TypeScript, I am trying to sort an array of Objects by the name of the actual object, not an object key. A name key does exist on these objects as well that is the same name of the actual object. I am trying to see where I am going wrong with my logic here. I have attempted to sort by the name key of the object with no success.

I have tried using the .sort() function in multiple ways.

An example array is as follows:

templateReports = [

{"Project Report": {name: "Project Report", docType: "Project"}},
{"Department Report": {name: "Department Report", docType: "Department"}},
{"Room Report": {name: "Room Report", docType: "Room"}}

]

I have tried the following:

templateReports.sort((a,b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));

I understand this doesn't work because to call the first name key in the array, I could do something like:

console.log(templateReports[0]["Project Report"].name);

and that would get me the name value for the first object in the array. So I know I would have to modify how I'm using the source function to be something like:

templateReports.sort((a,b) => (a[nameOfObject].name > b[nameOfNextObject].name) ? 1 : ((b[nameOfNextObject].name > a[nameOfObject].name) ? -1 : 0));

I'm trying to get it to sort alphabetically to become:

templateReports = [

{"Department Report": {name: "Department Report", docType: "Department"}},
{"Project Report": {name: "Project Report", docType: "Project"}},
{"Room Report": {name: "Room Report", docType: "Room"}}

]

How do I either a) accomplish this using the sort method or b) do something to sort by the actual name of an object?

Thank you.

Upvotes: 0

Views: 176

Answers (3)

mbdavis
mbdavis

Reputation: 4010

That's a weird object structure.

You can do it - but you need to figure out what the accessor of the property should be. How do you define this key of each object?

You could use the first key in the object: (disclaimer - is this maintainable?)

const accessSortingKey(object: Object): string {
    const key = Object.keys(object)[0];
    return key;
} 

const weirdArray = [
    {"Project Report": {name: "Project Report", docType: "Project"}},
    {"Department Report": {name: "Department Report", docType: "Department"}},
    {"Room Report": {name: "Room Report", docType: "Room"}}
];

weirdArray.sort((a, b) => {
   const aVal = accessSortingKey(a);
   const bVal = accessSortingKey(b);

   return aVal > bVal ? 1 : aVal < bVal ? -1 : 0;

});

Upvotes: 1

einarmagnus
einarmagnus

Reputation: 3592

When you have an object like this:

let o = {"Project Report": {name: "Project Report", docType: "Project"}}

the first string is the property name. i.e to get the values you have to write something like:

o["Project Report"].name // => "Project Report"

That creates a problem for you as you don't know beforehand what the name is of the only key inside the objects you are trying to sort by.

But you can ask an object for its keys with Object.keys():

let keys = Object.keys(o) // => ["Project Report"]

And since you know you have only on key per object in your list you can write something like this:

function getName(o) {
    return Object.keys(o)[0];
}

templateReports.sort((first, second) => getName(first).localeCompare(getName(second)));

Upvotes: 1

Cowabunghole
Cowabunghole

Reputation: 193

To answer your question, you can get the object key by calling Object.keys(obj)[0] which gets the first enumerable key. Since each of these objects has exactly one key-value pair, this will work fine. If you add a second key-value pair, this will NOT work.

My next question, then, is why the objects are in this configuration in the first place? Considering the object keys are simply the name value repeated, I would think it would make more sense to have an array of just the objects, no? I'm not sure what you gain from having each object nested in a second object.

Upvotes: 0

Related Questions