我从服务器获得了一些JSON数据。在我的JavaScript中,我想对它进行一些排序。我认为sort()函数会做我想要的。
然而,似乎JavaScript在到达时立即将JSON数据转换为Object。如果我尝试使用sort()方法,我会收到错误(使用Firebug进行测试)。
我环顾网络,每个人似乎都说,一方面,JSON对象已经是JavaScript数组,而且对象可以像数组一样对待。就像在this question上一样,在其中一个答案中,一个人说“[对象]是你的数据 - 你可以像对待数组那样访问它。”
然而,事实并非如此。 JavaScript不允许我在我的对象上使用sort()。而且由于默认的假设是它们都是一样的,所以似乎没有关于如何将Object转换为数组的任何指令,或强制JavaScript将其视为一个或类似的东西。 / p>
那么......我如何让JavaScript让这个数据作为数组处理并排序()呢?
我的对象的控制台日志输出如下所示(我希望能够按“级别”中的值排序):
OBJECT JSONdata
{
1: {
displayName: "Dude1",
email: "dude1@example.com<mailto:dude1@example.com>",
lastActive: 1296980700,
level: 57,
timeout: 12969932837
}, 2: {
displayName: "Dude2",
email: "dude2@example.com<mailto:dude2@example.com>",
lastActive: 1296983456,
level: 28,
timeout: 12969937382
}, 3: {
displayName: "Dude3",
email: "dude3@example.com<mailto:dude3@example.com>",
lastActive: 1296980749,
level: 99,
timeout: 129699323459
}
}
答案 0 :(得分:42)
Array.prototype.slice.call(arrayLikeObject)
是将数组类对象转换为数组的标准方法。
这只适用于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);
};
事实证明,您需要遍历对象并自行将其映射到数组。
var newArray = []
for (var key in object) {
newArray.push(key);
}
你混淆了数组和“关联数组”的概念。在JavaScript中,对象类似于关联数组,因为您可以以object["key"]
格式访问数据。它们不是真正的关联数组,因为对象是无序列表。
对象和数组有很大的不同。
使用下划线的示例:
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;
});
请参阅live example
答案 1 :(得分:7)
您应该能够将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"]
答案 2 :(得分:6)
如果您的JavaScript对象是类数组对象,即具有有效数字length
属性的Object实例,那么您可以直接使用许多 native 数组方法归功于call
方法。例如:
// Sorts the given objet in-place as if it was an array
Array.prototype.sort.call(yourObject);
因此,如果您知道要排序的条目数(How to efficiently count the number of keys/properties of an object in JavaScript?),您可以这样做:
yourObject.length = theNumberOfEntries;
Array.prototype.sort.call(yourObject);
// Optionally: delete yourObject.length;
请注意,这只会将由“0”,“1”,“2”,...等索引的属性排序为length - 1
,包括数组。该对象的其他属性不会被重新排序。
答案 3 :(得分:5)
这些答案大多过于复杂化问题或使用JQuery或Underscore,而OP从未要求过。
您可以将对象转换为如下数组:
myArray= Object.keys(data).map(function(key) { return data[key] });
将结果排序如下:
myArray.sort(function(x, y) {return x.level - y.level});
如果你需要id / index,那么你需要做更多的事情:
Object.keys(data).map(function(key) {
var obj = data[key];
obj.index = key;
return obj
});
答案 4 :(得分:2)
我最近在尝试按照其中一个属性对一组对象进行分组时偶然发现了这个问题,导致我无法对一个对象进行排序。
具体来说,这是一系列我希望按年分组的博客文章,并按降序排序。我使用了下划线的实用程序:
var grouped = _.groupBy(blogposts, function(post){
var date = new Date(post.publication_date)
return date.getFullYear()
})
//=> { 2010: [blogpost, blogpost,etc], 2011: [blogpost, etc] }
正如@Raynos解释的那样,在排序之前我必须首先使用某种数组......
事实证明,下划线(1.4)有一个很好的小实用工具,叫做pairs
,它会将你的对象的{key:value}映射到[key,value]数组中。相当于:
var paired = _.map(grouped, function(val, key){
return [key, val]
})
//=> [ [2010, [blogpost, blogpost, ...] ], [2011, [blogpost, blogpost, ...]]...]
从那里开始,您可以轻松地按每对的第一项进行排序。
这是最终结果:
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, ...]]...]
我确信虽然有更好,更高效的方式,但是来自ruby这个代码对我来说是可以理解的。
答案 5 :(得分:1)
jQuery提供了一个map函数,它将迭代数组或对象中的每个元素,并将结果映射到一个新数组中。
在jQuery 1.6之前,$ .map()仅支持遍历数组。
我们可以使用它将任何对象转换为数组,如下所示......
myArray = $.map(myObject, function (el) {
return el;
});
但是... 如果回调函数返回 null或未定义,则该值从数组删除,在大多数情况下这很有用,但如果您需要空值,则可能会导致问题myArray的。
jQuery为此提供了一个解决方案...... 将值作为具有单个值
的数组返回myArrayWithNulls = jQuery.map(myObject, function (el) {
return [el];
});
这是展示两种方法的小提琴: http://jsfiddle.net/chim/nFyPE/
答案 6 :(得分:1)
我编写了一个小函数来递归转换具有属性的对象,这些属性也可能是多维数组的对象。此代码依赖于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;
}
这是小提琴: http://jsfiddle.net/gGT2D/
注意:这是为了将最初为数组的对象转换回数组而编写的,因此任何非数组索引键值都将丢失。