通过子元素的道具对Json进行排序(比较表)

时间:2017-01-11 17:46:04

标签: javascript jquery json sorting

我正在尝试显示一个表格,其中包含一些项目的比较。我们的想法是以正确的方式排序(左侧更少,右侧更完整),如:

             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中查询节点,以便我能够实现逻辑。

欢呼

3 个答案:

答案 0 :(得分:1)

您可以定义一个基于某个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 :(得分:1)

您可以将计划视为二进制数,并将其用作排序标准。

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

答案 2 :(得分:1)

你将不得不以任何一种方式使用循环。如果您的JSON与您的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);
}

这没有经过测试,但这是一个粗略的草案,相当针对性的方法。