Я пытаюсь отобразить таблицу со сравнением некоторых предметов. Идея состоит в том, чтобы отсортировать правильным способом (меньше слева и более полно справа), например:

             Plan1  |  Plan2  |  Plan3
item1           X        X         X
item2           -        X         X
item3           -        -         X

Но API нашего вендора служит json неупорядоченным. Проблема в том, что у нас более 100 наименований и почти 20 планов, поэтому их невозможно фильтровать «жестким кодом».

JSON колоссальный, поэтому простая версия с минимумом будет (как в этом примере):

[
    {
        "Id": "1",
        "Name": "Item1",
        "Plans": [
            {
                "PlanMaster": "EPTV Max",
                "IdPlan": 1000,
                "HasPlan": true
            },
            {
                "PlanMaster": "EPTV",
                "IdPlan": 1001,
                "HasPlan": true
            },
            {
                "PlanMaster": "Web TV",
                "IdPlan": 1002,
                "HasPlan": true
            }
        ]
    },
    {
        "Id": "2",
        "Name": "Item2",
        "Plans": [
            {
                "PlanMaster": "EPTV Max",
                "IdPlan": 1000,
                "HasPlan": false
            },
            {
                "PlanMaster": "EPTV",
                "IdPlan": 1001,
                "HasPlan": true
            },
            {
                "PlanMaster": "Web TV",
                "IdPlan": 1002,
                "HasPlan": true
            }
        ]
    },
    {
        "Id": "3",
        "Name": "Item3",
        "Plans": [
            {
                "PlanMaster": "EPTV Max",
                "IdPlan": 1000,
                "HasPlan": false
            },
            {
                "PlanMaster": "EPTV",
                "IdPlan": 1001,
                "HasPlan": false
            },
            {
                "PlanMaster": "Web TV",
                "IdPlan": 1002,
                "HasPlan": true
            }
        ]
    }
]

Суть в том, как я могу перемещаться по json, чтобы запросить несколько вещей, таких как «Сколько у меня планов», «Список планет в порядке от меньшего количества элементов к большему» и т. Д ...

Как называется такая проблема "сортировки" / "сравнения"? Я пытался гуглить сортировку и т.д ... и не мог найти много. Я просто хочу знать, как я могу запрашивать узлы в JavaScript, чтобы я мог реализовать логику.

Ура

1
2Fast4YouBR 11 Янв 2017 в 20:46

3 ответа

Лучший ответ

Вы можете рассматривать планы как двоичное число и использовать его в качестве критерия сортировки.

var data = [{ "Id": "1", "Name": "Item1", "Plans": [{ "PlanMaster": "EPTV Max", "IdPlan": 1000, "HasPlan": true }, { "PlanMaster": "EPTV", "IdPlan": 1001, "HasPlan": true }, { "PlanMaster": "Web TV", "IdPlan": 1002, "HasPlan": true }] }, { "Id": "2", "Name": "Item2", "Plans": [{ "PlanMaster": "EPTV Max", "IdPlan": 1000, "HasPlan": false }, { "PlanMaster": "EPTV", "IdPlan": 1001, "HasPlan": true }, { "PlanMaster": "Web TV", "IdPlan": 1002, "HasPlan": true }] }, { "Id": "3", "Name": "Item3", "Plans": [{ "PlanMaster": "EPTV Max", "IdPlan": 1000, "HasPlan": false }, { "PlanMaster": "EPTV", "IdPlan": 1001, "HasPlan": false }, { "PlanMaster": "Web TV", "IdPlan": 1002, "HasPlan": true }] }];

data.sort(function (a, b) {
    function getRange(o) {
        var r = o.Plans.reduce(function (r, a) {
                return r * 2 + !a.HasPlan;
            }, 0);
      
        o.r = r; // just to show what's happen
        return r;
    }

    return getRange(a) - getRange(b);
});

console.log(data)
.as-console-wrapper { max-height: 100% !important; top: 0; }
1
Nina Scholz 11 Янв 2017 в 18:52

Вам придется использовать цикл в любом случае. Если ваш JSON настолько велик, насколько вы его представляете, проблема в эффективности. Вам нужно сделать все возможное, чтобы повысить эффективность.

Однако, если ваш JSON имеет 100 элементов (как вы говорите), это на самом деле не такой большой объем данных. Набор данных с миллионами строк? Конечно. Но сотня или даже несколько тысяч, вероятно, не будут представлять большую часть проблемы перфекта независимо от этого (очевидно, это также результат того, сколько вложенных свойств содержится в каждом элементе вашего набора данных, а также).

Что касается «навигации» по JSON, вам нужно просто просматривать их как объекты и избегать как можно большего количества методов доступа (поиск в кэше и т. Д.).

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

Пример чего-то более удобного для перфорирования, но менее удобного в обслуживании:

var i;
var j;
//Set up a 2-dimensional array where each array index represents the number of plans that each of it's members has. In this case, numPlans[0] contains all items that contain 0 plans, etc.
var plans = [[], [], []];
//Don't re-create variables on every loop, just re-assign
var item;
var numPlans;
var p;

for(i = 0; i < data.length; i++){ 
    item = data[i];
    p = item.Plans;
    numPlans = 0;
    for(j = 0; j < p.length; j++) {
        if(p[j].HasPlan) {
             numPlans++;
        }
    }
    plans[numPlans].push(item);
}

Это не проверено, но это черновик, достаточно перфорированный подход.

1
dudewad 11 Янв 2017 в 18:34

Вы можете определить универсальную функцию, которая сортирует массив на основе некоторой функции key:

let sortBy = (a, key) => a
    .map(x => [key(x), x])
    .sort((x, y) => x[0] > y[0] ? 1 : x[0] < y[0] ? -1 : 0)
    .map(x => x[1]);

Затем напишите некоторые специфические для задачи ключевые функции, например:

let numberOfPlans = item => item.Plans.filter(x => x.HasPlan).length;

И передать их sortBy:

let sortedData = sortBy(data, numberOfPlans);

Другой (и, возможно, лучший) вариант - загрузить эти данные в реляционную базу данных (например, sqlite) и использовать всю мощь SQL для получения всего, что вам нужно.

1
georg 11 Янв 2017 в 18:00