Search code examples
javascriptsortingnested-object

How to sort dynamic nested objects in javascript using bracket notation


I have a nested object upon which I want to run a sorting using a nested property. The sortDef will be dynamically set and it might have any value like year or director.name etc.

const mov = [
    {
        "id": "006",
        "name": "Schindler's List",
        "year": 1993,
        "director": {
            "name": "Steven Spielberg",
            "DOB": "01/28/1946"
        },
        "type": 1
    },
    {
        "id": "001",
        "name": "The Shawshank Redemption",
        "year": 1994,
        "director": {
            "name": "Frank Darabont",
            "DOB": "01/28/1959"
        },
        "type": 1
    }
];

const sortDef = {
  fieldName: 'director.name',
  sortingOrder: 'desc'
};

mov.sort((a, b) => (a[sortDef.fieldName].toLocaleLowerCase() > b[sortDef.fieldName].toLocaleLowerCase()) ? 1 : -1)

The sorting works when the sortDef fieldName is like year or name but it fails if it is director.name.


Solution

  • With a method that can read a nested property:

    const getValue = (obj,prop) => {
        var parts = prop.split(".");
        return parts.reduce( (a,v) => a[v], obj);
    }
    

    You just use that:

    const mov = [
        {
            "id": "006",
            "name": "Schindler's List",
            "year": 1993,
            "director": {
                "name": "Steven Spielberg",
                "DOB": "01/28/1946"
            },
            "type": 1
        },
        {
            "id": "001",
            "name": "The Shawshank Redemption",
            "year": 1994,
            "director": {
                "name": "Frank Darabont",
                "DOB": "01/28/1959"
            },
            "type": 1
        }
    ];
    
    const sortDef = {
      fieldName: 'director.name',
      sortingOrder: 'desc'
    };
    
    const getValue = (obj,prop) => {
        var parts = prop.split(".");
        return parts.reduce( (a,v) => a[v], obj);
    }
    
    
    mov.sort((a, b) => (getValue(a,sortDef.fieldName).toLocaleLowerCase() > getValue(b,sortDef.fieldName).toLocaleLowerCase()) ? 1 : -1)
    
    console.log(mov)