2014-04-03 49 views
1

我在使用Underscore时遇到了困难。我想按字母顺序排列下面的对象的值,并以相同的格式返回它。按值排序对象

{ 
    "accommodation" : "Accommodation", 
    "bed-breakfast" : "Bed & Breakfast", 
    "caravan-camping" : "Caravan & Camping", 
    "cottages" : "Cottages", 
    "friends-family" : "Friends & Family", 
    "health-spas" : "Health Spas", 
    "hostels" : "Hostels", 
    "hotels" : "Hotels", 
    "self-catering" : "Self Catering", 
    "backpacking" : "Backpacking", 
    "car-touring" : "Car Touring" 
} 

我设法对它进行排序,但它用索引值替换了键。有任何想法吗?这应该是相当直接的。我错过了什么?

在此先感谢!

+5

JS对象没有顺序。您无法以编程方式对对象进行排序。只有数组。 – Andy

+0

我只是想说,安迪:D –

+0

我强烈建议**不要**存储HTML转义的文本。在HTML上下文中使用它时,应将其转换为HTML。否则,你很早就混淆了你的数据方式,并且不能将它用于其他目的。 – Brad

回答

-1

感谢'亩太短的答案,它让我大部分的方式。但是,它需要转换回一个对象,经过一些摆弄之后,它非常简单。下面是完整的答案:

var sortedDataArr = _(data).chain() 
          .pairs() 
          .sortBy(_.last) 
          .value(); 

var sortedDataObj = _.object(sortedDataArr); 
+0

正如我上面所说的,这不能保证工作,因为在对象中没有指定的顺序。如果您需要按照特定顺序进行操作,则会使用错误的数据结构。 –

-3

JS对象没有顺序。您无法以编程方式对对象进行排序。只有阵列

不是真的。当您在对象上调用JSON.stringify时,输出字符串中属性的顺序是在该对象上定义属性的顺序。这同样适用于Object.keys(obj)for(var property in obj)(假设obj是您的对象)。你可以这样做:

var originalObject = { 
    "accommodation" : "Accommodation", 
    "bed-breakfast" : "Bed & Breakfast", 
    "caravan-camping" : "Caravan & Camping", 
    "cottages" : "Cottages", 
    "friends-family" : "Friends & Family", 
    "health-spas" : "Health Spas", 
    "hostels" : "Hostels", 
    "hotels" : "Hotels", 
    "self-catering" : "Self Catering", 
    "backpacking" : "Backpacking", 
    "car-touring" : "Car Touring" 
}; 
// map your object onto an array [key, value] 
var arr = _.map(originalObject, function(value, key) { 
    return [key, value]; 
}); 
// sort it by originalObject's values 
arr.sort(function(a, b) { 
    return a[1].localeCompare(b[1]); 
}); 
// create an object from an array 
var obj = _.object(arr); 

JSON.stringify(originalObject)产量:

"{"accommodation":"Accommodation","bed-breakfast":"Bed & Breakfast","caravan-camping":"Caravan & Camping","cottages":"Cottages","friends-family":"Friends & Family","health-spas":"Health Spas","hostels":"Hostels","hotels":"Hotels","self-catering":"Self Catering","backpacking":"Backpacking","car-touring":"Car Touring"}" 

JSON.stringify(obj)产量:

"{"accommodation":"Accommodation","backpacking":"Backpacking","bed-breakfast":"Bed & Breakfast","car-touring":"Car Touring","caravan-camping":"Caravan & Camping","cottages":"Cottages","friends-family":"Friends & Family","health-spas":"Health Spas","hostels":"Hostels","hotels":"Hotels","self-catering":"Self Catering"}" 
+1

你有备份你的订单断言的参考吗? –

3

不能可靠地排序JavaScript对象。 ES5 section 12.6.4说:

的力学和列举的属性顺序(步骤6.A在第一算法,在第二步骤7.A)没有被指定。

15.2.3.7说:

如果实现定义枚举的特定顺序对换的说法,同样的枚举顺序,必须使用命令在该算法的步骤3中的列表元素。

Section 15.2.3.14Object.keys)表示:

如果一个实现定义枚举的特定顺序对换在声明,相同的枚举顺序必须在该算法的步骤5中使用。

你也可以看8.6 The Object Type看看是否有任何提及属性顺序(提示:没有)。因此,在ES5中,属性顺序依赖于实现,唯一的限制或多或少是,如果在任何地方都有定义的顺序,则该顺序必须在任何地方都一样。

的ES6草案中包含类似的语言在section 9.1.11

机制和枚举未指定属性的顺序,但必须符合以下指定的规则。

所以在对象中绝对没有可移植和可靠的顺序。

没有,则无法通过JSON无论是作为JSON defines an object as去:

...一个无序的名称/值对

一些JavaScript实现订货会按广告订单对象但你不能依赖这一点。

你可以做的是你的对象转换为阵列的阵列像这样的东西最好的:

var sorted = _(obj).chain() 
        .pairs() 
        .sortBy(_.last) 
        .value(); 

或数组对象的-:

var sorted2 = _(obj).chain() 
        .pairs() 
        .sortBy(_.last) 
        .map(function(a) { return _([a]).object() }) 
        .value(); 

演示:http://jsfiddle.net/ambiguous/76ZPx/

+0

非常感谢非常详细的答案。然而,这只会返回一堆数组,因为我需要一个格式相同的对象。它已经让我99%的方式,虽然:) – DanV

+0

对象没有明确定义的顺序。除非你想从浏览器(现在和将来的版本)中采取非标准的行为,否则你所要求的是不可能的。 –