3
\$\begingroup\$

I had to sort a list of objects - {name:'name', email:'email} by their keys, ex. by email, so they all be rendered with email key/value pair as a first key/value pair and I was surprised about the solution i came up to - Object.assign() when i loop through array and assign email key/value pair to each object:

objects = [{name: 'name1', phone: 'phone1', email: 'email1'},
            {name: 'name1', phone: 'phone1', email: 'email1'},
            {name: 'name1', phone: 'phone1', email: 'email1'}]

sort(val) {    
  for (let i=0; i < this.objects.length; i++) {
    let temp = {};
    temp[val] = null; 
    this.objects[i] = Object.assign(temp, this.objects[i])  
  }
}

The rest is done by Angular's ChangeDetection. Are there better ways or can you tell any possible issues with this? (I still don't feel very proficient in Javascript, so just wondering)

Here is a StackBlitz's DEMO

\$\endgroup\$
  • \$\begingroup\$ Hm, quite not possible as the source was question in StackOverflow :) But I imagined a real scenario - from backend comes objects just as in my OP, but longer and with more key/value pairs and to make that list more "user friendly", need to sort it so its easier to read. And with solution in OP I wonder if Object.assign() won't cost much on performance behalf \$\endgroup\$ – Julius Dzidzevičius Apr 24 '18 at 12:38
  • \$\begingroup\$ It wasn't copy/paste. Only idea (idea of the challenge) was borrowed. Code is mine and I wonder if I should use this in the future, if needed \$\endgroup\$ – Julius Dzidzevičius Apr 24 '18 at 12:47
1
\$\begingroup\$

Object assign via ... operator

There is a sorter way to do the property order if you use the spread operator to assign properties.

function propOrderFirst(key,objects){
     for(var i = 0; i < objects.length; i++){
          objects[i] = {[key] : null, ...objects[i]};
     }
     return objects;
}

The problem is

const objs = [{name: 'name1', phone: 'phone1', email: 'email1'},
        {name: 'name1', phone: 'phone1', email: 'email2'},
        {name: 'name1', phone: 'phone1', email: 'email3'}];

const obj1 = obj[0];

objs = propOrderFirst("email",objs);

if(obj1 !== objs[0]) { // true as you have created a new instance 

Reorder in place

But you do lose the object reference that may not be the best option. You can reorder the object properties and still keep the object reference by using delete to remove properties.

A little more complex as you need to delete all the properties you want to move the new property position in-front of

function propOrderFirst(key, objects){
    const keys = Object.keys(objects[0]);  // assuming all objects have same properties
                                           // If not move this inside loop
    for (const object of objects) {
        const temp = {...object};     // get a copy of object
        for (const k of keys) { delete object[k] };  // remove all properties
        object[key] = temp[key];      // add the key you want first
        Object.assign(object, temp);  // assign the objects properties back
    }
    return objects;
 }

So now

const objs = [{name: 'name1', phone: 'phone1', email: 'email1'},
        {name: 'name1', phone: 'phone1', email: 'email2'},
        {name: 'name1', phone: 'phone1', email: 'email3'}];

const obj1 = obj[0];

objs = propOrderFirst("email",objs);

if(obj1 === objs[0]) { // true as you have reordered in place }
\$\endgroup\$
  • 1
    \$\begingroup\$ Nice. Looks like it solves my main concern - pollution of Javascript's memory. \$\endgroup\$ – Julius Dzidzevičius Apr 25 '18 at 5:12
  • 1
    \$\begingroup\$ @popStar ??? "pollution"? I don't know what that means. Your original code and the answer code all use the same amount of memory (excluding the small differences between the functions heap needs) When the function exits there will be no net change in the amount of memory requierment \$\endgroup\$ – Blindman67 Apr 25 '18 at 7:39
  • 1
    \$\begingroup\$ Garbage collection, if that isn't obvious. But now I see (was early morning). - you made a problem and solved it... In my case all objects are freed up, but in yours, you store a reference - obj1 = obj[0] so memory wont release it and in time could be polluted with thousands of those objects. Anyway, now I am pretty sure that in my OP all junk is being cleaned up \$\endgroup\$ – Julius Dzidzevičius Apr 25 '18 at 10:04
1
\$\begingroup\$

You are doing it in the most difficult way possible.

What you actually want to do is to define the order of properties, e.g:

const propertyOrder = ['name', 'phone', 'email'];

or

const propertyOrder = Object.keys(object[0]).sort(...);

and pass that order to your components with the object instead of using a random ordering of Object.keys.

\$\endgroup\$
1
\$\begingroup\$

Try the solutions standard library offers you first.

Arrays in javascript could be sorted by using array.sort()

which additionally accepts a comparer predicate

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

or alternatively

sort(function(a, b) {
  if (a.name > b.name) {
     return 1;
  }

  if (a.name < b.name) {
     return -1;
  }

  return 0;
});
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.