如何对 Javascript 对象进行排序,或将其转换为数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4929924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:49:30  来源:igfitidea点击:

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

javascriptarraysjsonsortingobject

提问by Questioner

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.

我有一些从服务器获取的 JSON 数据。在我的 JavaScript 中,我想对其进行一些排序。我认为 sort() 函数会做我想要的。

However, it seems that JavaScript is converting the JSON data into an Object immediately on arrival. If I try to use the sort() method, I get errors a-plenty (using Firebug for testing).

但是,JavaScript 似乎在 JSON 数据到达时立即将其转换为对象。如果我尝试使用 sort() 方法,我会得到很多错误(使用 Firebug 进行测试)。

I've looked around the net, and everyone seems to say that for one thing, JSON objects are already JavaScript arrays, and also that Objects can be treated just like arrays. Like over on this question, where in one of the answers, a guy says "The [Object object] is your data -- you can access it as you would an array."

我在网上找了一圈,似乎每个人都说,一方面,JSON 对象已经是 JavaScript 数组,而且对象可以像数组一样对待。就像在这个问题上一样,在其中一个答案中,有人说“[Object 对象] 是您的数据——您可以像访问数组一样访问它。”

However, that is not exactly true. JavaScript won't let me use sort() on my object. And since the default assumption is that they're all the same thing, there don't seem to be any instructions anywhere on how to convert an Object to an Array, or force JavaScript to treat it as one, or anything like that.

然而,事实并非如此。JavaScript 不允许我在我的对象上使用 sort()。而且由于默认假设它们都是相同的东西,因此似乎没有任何关于如何将对象转换为数组的说明,或强制 JavaScript 将其视为一个,或类似的内容。

So... how do I get JavaScript to let me treat this data as an array and sort() it?

那么...我如何让 JavaScript 让我将这些数据视为一个数组并对其进行排序()?

Console log output of my object looks like this (I want to be able to sort by the values in the "level"):

我的对象的控制台日志输出如下所示(我希望能够按“级别”中的值进行排序):

OBJECT JSONdata

对象 JSON 数据

{ 
1: {
    displayName: "Dude1",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980700, 
    level: 57, 
    timeout: 12969932837
}, 2: {
    displayName: "Dude2",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296983456,
    level: 28,
    timeout: 12969937382
}, 3: {
    displayName: "Dude3",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980749,
    level: 99,
    timeout: 129699323459
} 
}

回答by Raynos

Array.prototype.slice.call(arrayLikeObject)

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 argumentsobject. To convert a generic object to an array is a bit of a pain. Here's the source from underscore.js:

这仅适用于arguments对象。将通用对象转换为数组有点麻烦。下面是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.

您混淆了数组和“关联数组”的概念。在 JavaScript 中,对象有点像关联数组,因为您可以以object["key"]. 它们不是真正的关联数组,因为对象是无序列表。

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

查看现场示例

回答by alex

You should be able to convert a JavaScript object into an array like so...

您应该能够像这样将 JavaScript 对象转换为数组...

var obj = {
    '1': 'a',
    '2': 'b',
    '3': 'c'  
};

var arr = [];

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      arr.push(obj[key]);  
    }
}

console.log(arr); // ["a", "b", "c"]

See it on jsFiddle.

在 jsFiddle 上查看

回答by Luc125

If your JavaScript object is an array-like object, that is, an Object instance with a valid numerical lengthproperty, then you can directly use many nativeArray methods on it thanks to the callmethod. For example:

如果你的 JavaScript 对象是一个类似数组的对象,即一个具有有效数值length属性的 Object 实例,那么你可以直接在其上使用许多原生的Array 方法,这要归功于该call方法。例如:

// 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:

因此,如果您知道要排序的条目数(如何在 JavaScript 中有效地计算对象的键/属性的数量?),您可以执行以下操作:

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 - 1inclusive, like in an Array. The object's other properties will not be re-ordered.

请注意,这只会对由“0”、“1”、“2”、...索引的属性进行排序length - 1,例如在数组中。对象的其他属性不会重新排序。

回答by andyhasit

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

这些答案中的大多数都使问题过于复杂,或者使用了 JQuery 或 Underscore,而 OP 从未要求过这些。

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:

如果您需要 id/index,那么您需要做更多的事情:

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

回答by charlysisto

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...

正如@Raynos 所解释的,在排序之前我必须先得到某种数组......

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

事实证明,underscore (1.4) 有一个不错的小实用程序pairs,它可以将对象的 {key: value} 映射到 [key, value] 数组中。相当于:

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.

我确信虽然有更好、更高效的方式,但是来自 ruby​​ 的这段代码对我来说是可以立即理解的。

回答by chim

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

jQuery 提供了一个 map 函数,它将遍历数组或对象中的每个元素,并将结果映射到一个新数组中。

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

在 jQuery 1.6 之前, $.map() 仅支持遍历数组。

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 removedfrom the array, in most cases this is useful, but it can cause problems if you need null values in myArray.

但是...如果回调函数返回null 或 undefined,则该值将从数组中删除,在大多数情况下这很有用,但如果您需要 myArray 中的空值,它可能会导致问题。

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

jQuery为此提供了一个解决方案......将值作为具有单个值的数组返回

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

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

这是演示这两种方法的小提琴:http: //jsfiddle.net/chim/nFyPE/

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

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

回答by Isioma Nnodum

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.

我编写了一个小函数来递归地将具有属性的对象(也可能是对象)转换为多维数组。此代码依赖于 forEach 和 toArray 方法的下划线或 lodash。

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/

这是小提琴: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.

注意:这是为了将最初是数组的对象转换回数组,因此任何非数组索引键值都将丢失。