【问题标题】:Sort Keys in Javascript ObjectJavascript 对象中的排序键
【发布时间】:2015-06-19 19:50:06
【问题描述】:

我有一个 Javascript 对象,其中包含多种属性类型,包括简单字符串、对象、对象数组……等等。

我想按照以下规则对键进行排序:

'像字符串或数字这样的简单属性总是出现在包含数组或对象的更复杂的属性之前'

我编写了以下函数,几乎可以实现我想要实现的功能,但它将数组转换为对象。这不是期望的行为。谁能帮我创建一个函数,将数组保存为数组,同时对数组中的对象进行排序?

function sort(object){
    if (typeof object != "object" )
        return object;
    var keys = Object.keys(object);
    keys.sort(function(a,b){
            if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
        });

工作 jsfiddle:

http://jsfiddle.net/u01mn2py/3/

亲切的问候

【问题讨论】:

    标签: javascript sorting object key


    【解决方案1】:

    从 ECMAScript 2015 (ES6) 开始,对象的 自己的 属性 do have order 用于某些操作,尽管依赖它很少是一个好主意。如果你想要排序,通常最好使用数组或类似的。

    顺序是:

    1. keys 成为一个新的空列表。
    2. 对于作为整数索引的 O 的每个自己的属性键 P,按数字索引升序排列
      • 添加P作为keys的最后一个元素。
    3. 对于 O 的每个自己的属性键 P,它是一个字符串但不是整数索引,按属性创建顺序
      • 添加P作为keys的最后一个元素。
    4. 对于作为符号的 O 的每个自己的属性键 P,按属性创建顺序
      • 添加P作为keys的最后一个元素。
    5. 返回

    这是“自己的”属性。 我认为没有任何外部可用的操作可以为所有属性(包括继承的属性)定义所需的顺序。 (for-in 不需要遵循上述顺序,即使在 ES2015+ 中也是如此。) 从 ES2019 开始,for-in does have a defined order (有一些例外)

    这意味着,只要我们的所有键都不符合整数索引的条件,就可以在兼容的引擎上执行您要求的操作。

    JSON 仍然没有顺序,但 JavaScript 规范要求 JSON.stringify 使用上述顺序。

    我不是说我建议它。 :-)

    function sort(object) {
        // Don't try to sort things that aren't objects
        if (typeof object != "object") {
            return object;
        }
    
        // Don't sort arrays, but do sort their contents
        if (Array.isArray(object)) {
            object.forEach(function(entry, index) {
                object[index] = sort(entry);
            });
            return object;
        }
    
        // Sort the keys
        var keys = Object.keys(object);
        keys.sort(function (a, b) {
            var atype = typeof object[a],
                btype = typeof object[b],
                rv;
            if (atype !== btype && (atype === "object" || btype === "object")) {
                // Non-objects before objects
                rv = atype === 'object' ? 1 : -1;
            } else {
                // Alphabetical within categories
                rv = a.localeCompare(b);
            }
            return rv;
        });
    
        // Create new object in the new order, sorting
        // its subordinate properties as necessary
        var newObject = {};
        keys.forEach(function(key) {
            newObject[key] = sort(object[key]);
        });
        return newObject;
    }
    

    现场示例(我也是updated the fiddle):

    function sort(object) {
        // Don't try to sort things that aren't objects
        if (typeof object != "object") {
            return object;
        }
        
        // Don't sort arrays, but do sort their contents
        if (Array.isArray(object)) {
            object.forEach(function(entry, index) {
                object[index] = sort(entry);
            });
            return object;
        }
        
        // Sort the keys
        var keys = Object.keys(object);
        keys.sort(function (a, b) {
            var atype = typeof object[a],
                btype = typeof object[b],
                rv;
            if (atype !== btype && (atype === "object" || btype === "object")) {
                // Non-objects before objects
                rv = atype === 'object' ? 1 : -1;
            } else {
                // Alphabetical within categories
                rv = a.localeCompare(b);
            }
            return rv;
        });
        
        // Create new object in the new order, sorting
        // its subordinate properties as necessary
        var newObject = {};
        keys.forEach(function(key) {
            newObject[key] = sort(object[key]);
        });
        return newObject;
    }
    
    var object = {
        family: [{
            home: {
                city: 'Madrid'
            },
            birth: {
                city: 'Madrid'
            },
            name: 'John',
            age: 32
    
        }, {
            home: {
                city: 'London'
            },
            birth: {
                city: 'Paris'
            },
            name: 'Marie',
            age: 25
        }],
        name: 'Dani',
        age: 33
    };
    var sortedObject = sort(object);
    document.getElementById('container').innerHTML = JSON.stringify(sortedObject, null, '\t');
    <pre id="container">
    </pre>

    (您没有要求在类别中按字母顺序排列,但它似乎是合理的。)

    这适用于当前的 Chrome、Firefox 和 IE11。

    【讨论】:

    • 我只需要将对象显示为有序 JSON(遵循我的规则),但 JSON.stringify 没有任何排序选项。我该怎么做?
    • @wildbyte:对。 JSON 中的属性也没有顺序。如果您想要一个以特定顺序列出属性的 JSON 字符串,您必须构建自己的函数来执行此操作。 (前段时间我不得不这样做,但遗憾的是无法共享该代码。但这并不难,您可以使用JSON.stringify 来处理其中的一部分,但您必须定义递归和迭代。大约花了 15代码行。)
    • @wildbyte:现在 ECMAScript 2015 已经完成,我已经更新了答案。
    【解决方案2】:

    我知道我无法在 javascript 属性顺序上进行中继,但我需要直观地显示已排序的 JSON。这样解决:

    http://jsfiddle.net/u01mn2py/4/

    function sort(object){
        if (typeof object != "object" ) // Not to sort the array
            return object;
        var keys = Object.keys(object);
        keys.sort(function(a,b){
                if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
            });
        if( Object.prototype.toString.call( object ) === '[object Array]' ) {
            var newObject = [];
         } else {
            var newObject = {}; }
    
         for (var i = 0; i < keys.length; i++){
                newObject[keys[i]] = sort(object[keys[i]])
          }
        return newObject;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多