我正在尝试显示一个表格,其中包含一些项目的比较。我们的想法是以正确的方式排序(左侧更少,右侧更完整),如:
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中查询节点,以便我能够实现逻辑。
欢呼答案 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);
}
这没有经过测试,但这是一个粗略的草案,相当针对性的方法。