How to sort a Javascript object, or convert it to an array?

前端 未结 7 575
囚心锁ツ
囚心锁ツ 2020-12-13 04:13

I have some JSON data that I get from a server. In my JavaScript, I want to do some sorting on it. I think the sort() function will do what I want.

However, it seems

相关标签:
7条回答
  • 2020-12-13 04:31

    jQuery offers a map function, which will iterate through each element in an array or object and map the results into a new array.

    Prior to jQuery 1.6, $.map() supported traversing arrays only.

    We can use this to convert any object to an array as follows...

      myArray = $.map(myObject, function (el) {
        return el;
      });
    

    But... if the callback function returns null or undefined, then that value is removed from the array, in most cases this is useful, but it can cause problems if you need null values in myArray.

    jQuery offers a solution for this... return the value as an array with the single value

    myArrayWithNulls = jQuery.map(myObject, function (el) {
      return [el];
    });
    

    Here's a fiddle demonstrating the two approaches: http://jsfiddle.net/chim/nFyPE/

    http://jsperf.com/object-to-array-jquery-2

    0 讨论(0)
  • 2020-12-13 04:40

    Most of these answers over-complicate the issue or use JQuery or Underscore whereas the OP never asked for those.

    You can convert an object to an array like this:

    myArray= Object.keys(data).map(function(key) { return data[key] });
    

    And sort the result like this:

    myArray.sort(function(x, y) {return x.level - y.level});
    

    If you need the id/index, then you need to do a bit more:

    Object.keys(data).map(function(key) { 
      var obj = data[key];
      obj.index = key;
      return obj 
    });
    
    0 讨论(0)
  • 2020-12-13 04:41

    I have stumbled upon that problem recently while trying to group an array of objects by one of it's properties, resulting in one object I could therefore not sort.

    Concretely it's an array of blog posts I wanted to group by year and have them sorted by descending years. I used underscore's utility :

    var grouped = _.groupBy(blogposts, function(post){
      var date = new Date(post.publication_date)
      return date.getFullYear()
    })
    //=> { 2010: [blogpost, blogpost,etc], 2011: [blogpost, etc] }
    

    As @Raynos explained I had to end up with some sort of array first before sorting it...

    It turns out underscore (1.4) has a nice little utility called pairs which will map the {key: value} of your object in an array of [key, value]. The equivalent of :

    var paired = _.map(grouped, function(val, key){
      return [key, val]
    })
    //=> [ [2010, [blogpost, blogpost, ...] ], [2011, [blogpost, blogpost, ...]]...]
    

    From there on you can easily sort by the first term of each pair.

    Here's the end result:

    var grouped = _.groupBy(result.resource, function(resource){
      var date = new Date(resource.pub_date)
      return date.getFullYear() //+ "." + (date.getMonth()+1)
    })
    
    var paired = _.pairs(grouped)
    
    var sorted = _.sortBy(paired, function(pairs){
      return -parseInt(pairs[0])
    })
    
    return sorted;
    // Giving me the expected result:
    //=> [ [2013, [blogpost, blogpost, ...] ], [2012, [blogpost, blogpost, ...]]...]
    

    I'm sure though there's a better and more performant way, but coming from ruby this code is immediately understandable for me.

    0 讨论(0)
  • 2020-12-13 04:43

    Array.prototype.slice.call(arrayLikeObject)

    is the standard way to convert and an array-like object to an array.

    That only really works for the arguments object. To convert a generic object to an array is a bit of a pain. Here's the source from underscore.js:

    _.toArray = function(iterable) {
        if (!iterable)                return [];
        if (iterable.toArray)         return iterable.toArray();
        if (_.isArray(iterable))      return iterable;
        if (_.isArguments(iterable))  return slice.call(iterable);
        return _.values(iterable);
    };
    
    _.values = function(obj) {
        return _.map(obj, _.identity);
    };
    

    Turns out you're going to need to loop over your object and map it to an array yourself.

    var newArray = []
    for (var key in object) {
        newArray.push(key);
    }
    

    You're confusing the concepts of arrays and "associative arrays". In JavaScript, objects kind of act like an associative array since you can access data in the format object["key"]. They're not real associative arrays since objects are unordered lists.

    Objects and arrays are vastly different.

    An example of using underscore:

    var sortedObject = _.sortBy(object, function(val, key, object) {
        // return an number to index it by. then it is sorted from smallest to largest number
        return val;
    });
    

    See live example

    0 讨论(0)
  • 2020-12-13 04:44

    If your JavaScript object is an array-like object, that is, an Object instance with a valid numerical length property, then you can directly use many native Array methods on it thanks to the call method. For example:

    // Sorts the given objet in-place as if it was an array
    Array.prototype.sort.call(yourObject);
    

    So if you know the number of entries to be sorted (How to efficiently count the number of keys/properties of an object in JavaScript?), you can do:

    yourObject.length = theNumberOfEntries;
    Array.prototype.sort.call(yourObject);
    // Optionally: delete yourObject.length;
    

    Note that this will only sort properties indexed by "0", "1", "2", ... to length - 1 inclusive, like in an Array. The object's other properties will not be re-ordered.

    0 讨论(0)
  • 2020-12-13 04:47

    I wrote a small function to recursively convert an object with properties that may also be objects to a multi-dimensional array. This code is dependent on underscore or lodash for the forEach and toArray methods.

    function deepToArray(obj) {
        var copy = [];
    
    
        var i = 0;
        if (obj.constructor == Object ||
            obj.constructor == Array) {
    
            _.forEach(obj, process);
    
        } else {
    
            copy = obj;
    
        }
    
    
        function process(current, index, collection) {
    
            var processed = null;
            if (current.constructor != Object &&
                current.constructor != Array) {
                processed = current;
            } else {
                processed = deepToArray(_.toArray(current));
            }
    
            copy.push(processed);
    
        }
    
        return copy;
    }
    

    Here is the fiddle: http://jsfiddle.net/gGT2D/

    Note: This was written to convert an object that was originally an array back into an array, so any non-array index key values will be lost.

    0 讨论(0)
提交回复
热议问题