对 Javascript 对象中的键进行排序 [英] Sort Keys in Javascript Object

查看:33
本文介绍了对 Javascript 对象中的键进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Javascript 对象,它包含多种属性类型,包括简单的字符串、对象、对象数组......等等.

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

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

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

函数排序(对象){if (typeof object != "object" )返回对象;var 键 = Object.keys(object);键.排序(功能(a,b){if (typeof(object[a])!=='object') { return -1 } else { return 1 }});

工作 jsfiddle:

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

亲切的问候

解决方案

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

顺序是:

<块引用>

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

那是针对自己的"属性的.我认为没有任何外部可用的操作可以为所有属性(包括继承的属性)定义所需的顺序.(for-in 不需要遵循上述顺序,即使在 ES2015+ 中也是如此.) 从 ES2019 开始,for-in 确实有定义的顺序 (有一些例外).

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

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

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

function sort(object) {//不要试图对不是对象的东西进行排序如果(对象类型!=对象"){返回对象;}//不要对数组进行排序,而是对它们的内容进行排序如果(Array.isArray(对象)){object.forEach(function(entry, index) {对象[索引] = 排序(条目);});返回对象;}//对键进行排序var 键 = Object.keys(object);键.排序(功能(a,b){var atype = typeof object[a],btype = typeof object[b],房车;if (atype !== btype && (atype === "object" || btype === "object")) {//对象之前的非对象rv = atype === '对象' ?1:-1;} 别的 {//按字母顺序分类rv = a.localeCompare(b);}返回房车;});//按照新的顺序创建新对象,排序//必要时它的从属属性var newObject = {};键.forEach(功能(键){newObject[key] = sort(object[key]);});返回新对象;}

Live Example(我也更新了小提琴):

function sort(object) {//不要试图对不是对象的东西进行排序如果(对象类型!=对象"){返回对象;}//不要对数组进行排序,而是对它们的内容进行排序如果(Array.isArray(对象)){object.forEach(function(entry, index) {对象[索引] = 排序(条目);});返回对象;}//对键进行排序var 键 = Object.keys(object);键.排序(功能(a,b){var atype = typeof object[a],btype = typeof object[b],房车;if (atype !== btype && (atype === "object" || btype === "object")) {//对象之前的非对象rv = atype === '对象' ?1:-1;} 别的 {//按字母顺序分类rv = a.localeCompare(b);}返回房车;});//按照新的顺序创建新对象,排序//必要时它的从属属性var newObject = {};键.forEach(功能(键){newObject[key] = sort(object[key]);});返回新对象;}变量对象 = {家庭: [{家: {城市:'马德里'},出生:{城市:'马德里'},name: '约翰',年龄:32}, {家: {城市:伦敦"},出生:{城市:'巴黎'},name: '玛丽',年龄:25}],name: 'Dani',年龄:33};var sortedObject = sort(object);document.getElementById('container').innerHTML = JSON.stringify(sortedObject, null, '	');

(您没有要求在类别内按字母顺序排列,但扔进去似乎是合理的.)

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

I have a Javascript Object that contains a mix of property types including simple strings, objects, arrays of objects... and so on.

I would like to sort the keys following this rule:

'Simple properties like strings or numbers appears always before more complex properties that contains arrays or objects'

I wrote the following function, that almost do what I am trying to achieve, but it converts the arrays into objects. This is not the desired behaviour. Can anybody help me to create a function that keep arrays as arrays and at the same time it sorts the objects inside arrays?

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 }
        });

Working jsfiddle:

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

Kind Regards

解决方案

As of ECMAScript 2015 (ES6), an object's own properties do have order for some operations, although relying on it is rarely a good idea. If you want order, usually it's best to use an array or similar.

The order is:

  1. Let keys be a new empty List.
  2. For each own property key P of O that is an integer index, in ascending numeric index order
    • Add P as the last element of keys.
  3. For each own property key P of O that is a String but is not an integer index, in property creation order
    • Add P as the last element of keys.
  4. For each own property key P of O that is a Symbol, in property creation order
    • Add P as the last element of keys.
  5. Return keys.

That's for "own" properties. I don't think there are any externally-available operations that define a required order for all properties including inherited ones. (for-in is not required to follow the order above, not even in ES2015+.) As of ES2019, for-in does have a defined order (with some exceptions).

This means that it's probably possible to do what you asked, on a compliant engine, provided none of our keys qualifies as as an integer index.

JSON still has no order, but JSON.stringify is required by the JavaScript spec to use the order described above.

I'm not saying I suggest it. :-)

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;
}

Live Example (I also 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, '	');

<pre id="container">
</pre>

(You didn't ask for alphabetical within categories, but it seemed a reasonable thing to throw in.)

That works for me on current Chrome, Firefox, and IE11.

这篇关于对 Javascript 对象中的键进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆