Как отсортировать объект JSON по вложенному значению?

У меня есть вызов ajax, который возвращает объект JSON, который довольно сложный, и мне сложно его сортировать.

Мой вызов:

$.post('/reports-ajax',arguments, function(data) {}

Ответ:

{
"10001":{
    "unitname":"Fort Worth",
    "discounts":{"12-02-2012":"34.810000","12-03-2012":"20.810000","12-04-2012":"27.040000"},
    "gross":{"12-02-2012":"56.730000","12-03-2012":"19.350000","12-04-2012":"66.390000"},
    "net":{"12-02-2012":"61.920000","12-03-2012":"98.540000","12-04-2012":"39.350000"},
    "discounts_total":82.66,
    "gross_total":82.47,
    "net_total":99.81,
    "number":10001
    },
"10002":{
    "unitname":"Dallast",
    "discounts":{"12-02-2012":"12.600000","12-03-2012":"25.780000","12-04-2012":"47.780000","12-05-2012":"45.210000"},
    "gross":{"12-02-2012":"29.370000","12-03-2012":"91.110000","12-04-2012":"60.890000","12-05-2012":"51.870000"},
    "net":{"12-02-2012":"16.770000","12-03-2012":"65.330000","12-04-2012":"13.110000","12-05-2012":"06.660000"},
    "discounts_total":131.37,
    "gross_total":33.24,
    "net_total":101.87,
    "number":10002
    },
"32402":{
    "unitname":"Austin",
    "discounts":{"12-05-2012":"52.890000","12-02-2012":"22.430000","12-03-2012":"58.420000","12-04-2012":"53.130000"},
    "gross":{"12-05-2012":"25.020000","12-02-2012":"2836.010000","12-03-2012":"54.740000","12-04-2012":"45.330000"},
    "net":{"12-04-2012":"92.200000","12-05-2012":"72.130000","12-02-2012":"13.580000","12-03-2012":"96.320000"},
    "discounts_total":186.87,
    "gross_total":161.1,
    "net_total":174.23,
    "number":32402
    }
}

Я просматриваю функцию со стандартным каждым вызовом и делаю некоторые потрясающие вещи с помощью высокопроизводительных диаграмм, но теперь я пытаюсь сортировать ответы по вызову net_total, и я не могу понять это.

Я пробовал .sort(), и он ошибается, что его не является функцией. Я читал какое-то время, но думаю, что я не нахожу правильных результатов. Это выглядело многообещающим: Сортировка массива объектов JavaScript, но с ошибкой .sort не является функцией. Кажется, что большинство .sort находятся на [] массивах не полных объектов.

Любая помощь будет принята с благодарностью.

Ответы

Ответ 1

Сортировка объектов не имеет смысла, поскольку ключи объектов не имеют позиционного значения. Например, это:

{ a:1, b:2 }

и это:

{ b:2, a:1 }

- это точно такой же объект. Они не просто похожи, они одинаковы.

Ничто в javascript per se не дает объектным ключам любое позиционное значение. Некоторые люди, возможно, ошибаются в убеждении, что:

for (var key in obj) {

выполняет итерацию через ключи объектов в определенной последовательности. Но это неправильно. Вы всегда должны считать, что цикл for .. in обрабатывает ключи объектов в случайном порядке, всегда, все время.

Очевидно, что если вы собираетесь писать веб-браузер, вы не собираетесь создавать генератор случайных чисел для анализа цикла for .. in. Поэтому большинство веб-браузеров имеют случайную стабильность в отношении того, как цикл for .. in обрабатывает ключи объектов.

Разработчики, которые изучают javascript, играя в браузере, могут понять, что их браузер выполняет итерацию через объекты в алфавитном порядке, например, или порядок добавления ключей к объекту. Но это совершенно случайно, и на него нельзя положиться. Поставщик браузера может изменить это поведение в будущем, не нарушая совместимости в обратном направлении (за исключением ошибок с ошибками, написанных людьми, которые считают, что объекты имеют порядок сортировки). Не говоря уже о том, что разные браузеры имеют разные реализации javascript и поэтому не обязательно имеют одинаковую внутреннюю сортировку ключей объектов.

Все вышеперечисленное относится к точке. "Порядок сортировки ключей" не имеет никакого смысла в javascript, и любое наблюдаемое поведение - это просто детализация реализации. Короче говоря, объект javascript не имеет порядка клавиш, просто предположите, что он случайный.


Решение

Теперь, что вы действительно пытаетесь сделать, это не сортировать объект (вы не можете, это не имеет смысла). То, что вы действительно пытаетесь сделать, - это обработать атрибуты объекта в определенном порядке. Решение состоит в том, чтобы просто создать массив (который имеет порядок сортировки) ключей объектов, а затем обработать объект с помощью этого массива:

// First create the array of keys/net_total so that we can sort it:
var sort_array = [];
for (var key in Response) {
    sort_array.push({key:key,net_total:Response[key].net_total});
}

// Now sort it:
sort_array.sort(function(x,y){return x.net_total - y.net_total});

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
    var item = Response[sort_array[i].key];

    // now do stuff with each item
}

Ответ 2

У вас там нет массива и нет порядка, поэтому вам придется преобразовать его в массив, чтобы вы могли его заказать.

Смутно:

var array = [];
$.each(data, function(key, value) {
    array.push(value);
});
array.sort(function(a, b) {
    return a.net_total - b.net_total;
});

Live Example | Источник

Как указывает GolezTroi в комментариях, обычно вышеуказанное потеряет ключ, в котором каждая запись хранится в data, и поэтому вы должны добавить ее обратно в первый цикл $.each выше, но в этом случае записи уже имеют ключ на них (как number), поэтому нет необходимости.

Или вы можете заменить первый $.each на $.map:

var array = $.map(data, function(entry) {
    return entry;
});
// ...and then sort etc.

... в зависимости от того, что вы предпочитаете.