Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
626 views
in Technique[技术] by (71.8m points)

sorting - Sort Keys in Javascript Object

I have a Javascript Object that contains a mix of property types including simple strings, objects, arrays of objects... and so on.

I would like to sort the keys following this rule:

'Simple properties like strings or numbers appears always before more complex properties that contains arrays or objects'

I wrote the following function, that almost do what I am trying to achieve, but it converts the arrays into objects. This is not the desired behaviour. Can anybody help me to create a function that keep arrays as arrays and at the same time it sorts the objects inside arrays?

function sort(object){
    if (typeof object != "object" )
        return object;
    var keys = Object.keys(object);
    keys.sort(function(a,b){
            if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
        });

Working jsfiddle:

http://jsfiddle.net/u01mn2py/3/

Kind Regards

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As of ECMAScript 2015 (ES6), an object's own properties do have order for some operations, although relying on it is rarely a good idea. If you want order, usually it's best to use an array or similar.

The order is:

  1. Let keys be a new empty List.
  2. For each own property key P of O that is an integer index, in ascending numeric index order
    • Add P as the last element of keys.
  3. For each own property key P of O that is a String but is not an integer index, in property creation order
    • Add P as the last element of keys.
  4. For each own property key P of O that is a Symbol, in property creation order
    • Add P as the last element of keys.
  5. Return keys.

That's for "own" properties. I don't think there are any externally-available operations that define a required order for all properties including inherited ones. (for-in is not required to follow the order above, not even in ES2015+.) As of ES2019, for-in does have a defined order (with some exceptions).

This means that it's probably possible to do what you asked, on a compliant engine, provided none of our keys qualifies as as an integer index.

JSON still has no order, but JSON.stringify is required by the JavaScript spec to use the order described above.

I'm not saying I suggest it. :-)

function sort(object) {
    // Don't try to sort things that aren't objects
    if (typeof object != "object") {
        return object;
    }

    // Don't sort arrays, but do sort their contents
    if (Array.isArray(object)) {
        object.forEach(function(entry, index) {
            object[index] = sort(entry);
        });
        return object;
    }

    // Sort the keys
    var keys = Object.keys(object);
    keys.sort(function (a, b) {
        var atype = typeof object[a],
            btype = typeof object[b],
            rv;
        if (atype !== btype && (atype === "object" || btype === "object")) {
            // Non-objects before objects
            rv = atype === 'object' ? 1 : -1;
        } else {
            // Alphabetical within categories
            rv = a.localeCompare(b);
        }
        return rv;
    });

    // Create new object in the new order, sorting
    // its subordinate properties as necessary
    var newObject = {};
    keys.forEach(function(key) {
        newObject[key] = sort(object[key]);
    });
    return newObject;
}

Live Example (I also updated the fiddle):

function sort(object) {
    // Don't try to sort things that aren't objects
    if (typeof object != "object") {
        return object;
    }
    
    // Don't sort arrays, but do sort their contents
    if (Array.isArray(object)) {
        object.forEach(function(entry, index) {
            object[index] = sort(entry);
        });
        return object;
    }
    
    // Sort the keys
    var keys = Object.keys(object);
    keys.sort(function (a, b) {
        var atype = typeof object[a],
            btype = typeof object[b],
            rv;
        if (atype !== btype && (atype === "object" || btype === "object")) {
            // Non-objects before objects
            rv = atype === 'object' ? 1 : -1;
        } else {
            // Alphabetical within categories
            rv = a.localeCompare(b);
        }
        return rv;
    });
    
    // Create new object in the new order, sorting
    // its subordinate properties as necessary
    var newObject = {};
    keys.forEach(function(key) {
        newObject[key] = sort(object[key]);
    });
    return newObject;
}

var object = {
    family: [{
        home: {
            city: 'Madrid'
        },
        birth: {
            city: 'Madrid'
        },
        name: 'John',
        age: 32

    }, {
        home: {
            city: 'London'
        },
        birth: {
            city: 'Paris'
        },
        name: 'Marie',
        age: 25
    }],
    name: 'Dani',
    age: 33
};
var sortedObject = sort(object);
document.getElementById('container').innerHTML = JSON.stringify(sortedObject, null, '');
<pre id="container">
</pre>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...