【问题标题】:Sorting a Javascript object by value按值对 Javascript 对象进行排序
【发布时间】:2011-11-16 15:07:20
【问题描述】:

在我的 Javascript 应用程序中,我有一个对象,我需要能够通过内部对象中的值对数组进行排序。

例如:

{
    a : {
        timestamp: xxxxxx
        other : yyyyyy
    },
    b : {
        timestamp: xxxxxx
        other : yyyyyy
    },
    c : {
        timestamp: xxxxxx
        other : yyyyyy
    }
}

我需要做的是管理这个数据集并根据每个内部对象的时间戳对数组重新排序。

我可以通过哪些方式做到这一点?

更新:

我最初的想法是这样做:

{
    a : {},
    b : {},
    c : {},
    _ : [
        c, a, b //Key's Only
    ]
}

然后根据这些值重新索引对象,这将解决如何索引对象,但是当我插入一个新元素时,我还必须重新生成 _ 索引关系,这似乎需要付出很多努力.

【问题讨论】:

    标签: javascript arrays sorting map object-literal


    【解决方案1】:

    您可以将数据复制到数组中,然后对其进行排序:

    var data = {
        a : {
            timestamp: 11111,
            other : "xxx"
        },
        b : {
            timestamp: 22222,
            other : "yyy"
        },
        c : {
            timestamp: 33333,
            other : "zzz"
        }
    };
    
    var output = [];
    
    // copy items to an array so they can be sorted
    for (var key in data) {
        data[key].key = key;   // save key so you can access it from the array (will modify original data)
        output.push(data[key]);
    }    
    
    output.sort(function(a,b) {
        return(a.timestamp - b.timestamp);
    });
    

    将此作为输出生成(注意我将原始键添加到对象中,以便可以从数组中访问它):

    [{"timestamp":11111,"other":"xxx","key":"a"},
    {"timestamp":22222,"other":"yyy","key":"b"},
    {"timestamp":33333,"other":"zzz","key":"c"}]
    

    你可以在这里看到这个工作:http://jsfiddle.net/jfriend00/hXpkP/

    【讨论】:

    • 不要忘记对象属性的 hasOwnProperty 测试,否则您可能会包含继承属性。
    【解决方案2】:

    您可以创建自定义比较器函数并使用数组的内置排序函数。看到这个post

    【讨论】:

      【解决方案3】:

      正如其他人已经说过的,您正在处理一个关联对象。不是数组。对象没有顺序。

      如果您希望保持原样,而是对键数组进行排序,您可以这样做:

      var obj = {
          a : {
              timestamp: xxxxxx
              other : yyyyyy
          },
          b : {
              timestamp: xxxxxx
              other : yyyyyy
          },
          c : {
              timestamp: xxxxxx
              other : yyyyyy
          }
      };
      
      var keys = [];
      for(var key in obj) {
          keys.push(key);
      }
      
      keys.sort(function(a, b) {
          return obj[a].timestamp - obj[b].timestamp;
      });
      

      现在您可以通过数组值访问对象(例如 obj[keys[0]]、obj[keys[1]] 等)。这假设时间戳是数字的。如果它们是日期对象,则排序应为:

      keys.sort(function(a, b) {
          return +obj[a].timestamp - (+obj[b].timestamp);
      });
      

      如果时间戳实际上是表示日期时间的字符串(如“2012 年 8 月 2 日”),那么它应该是:

      keys.sort(function(a, b) {
          return +new Date(obj[a].timestamp) - (+new Date(obj[b].timestamp));
      });
      

      所以在你的场景中使用最有意义的东西。

      【讨论】:

        【解决方案4】:

        您处理的不是数组,而是属性值为abc 的对象

        你没有理由需要它们以特定的顺序,因为你不能真正以任何特定的顺序循环它们。

        如果您使用数组,这将是微不足道的(使用 sort)...

        var array = [
            {
                timestamp: xxxxxx
                other : yyyyyy
            },
            {
                timestamp: xxxxxx
                other : yyyyyy
            },
            {
                timestamp: xxxxxx
                other : yyyyyy
            }
        ];
        
        array.sort(function(a,b) {
            return a.timestamp - b.timestamp;
        });
        

        【讨论】:

        • 数组的问题是它们没有基于字符串的索引,并且可以快速访问需要基于字符串的索引的元素。
        • 所有 javascript 索引 are 字符串和 javascript 数组 are 对象,它们只有一些额外有用的功能...您特别喜欢的功能...jsfiddle.net/Mb8xC
        【解决方案5】:

        Javascript 对象是不是关联数组。它们的行为可能相似,但它们并不相同。 Javascript 没有关联数组。

        虽然关联数组具有顺序概念,但 Javascript 对象根本不与它们共享此特定功能。就其本质而言,对象是没有顺序的。

        所以,回答你的问题:你不能订购它们......

        【讨论】:

        • 当然,对象没有顺序,但这并不意味着没有可能的解决方案。
        • 您可以创建索引、键值哈希表和“顺序”,并在需要时使用从一个数组到对象的引用