通过对象数组中的值为对象分配等级
Assign ranks to objects by values in an array of objects
我有一个像这样的对象数组:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15 },
{ keyone:'s', keytwo: 'anna', keythree: 10, keyfour: 15 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
我想根据 keythree
和 keyfour
的值,在组内以及在整个数据集中为每个对象分配等级。我该怎么做?
更新:我在上面的代码中描述了等级。
结果对象:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15, rankgroup: 3, rankall: 4 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 4, rankall: 5 },
{ keyone:'s', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 2, rankall: 2 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15, rankgroup: 1, rankall: 1 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
我正在使用 lodash
。我的想法是首先根据这些键对数组进行排序,然后遍历原始对象,通过比较另一个键插入排序后的索引。这是我试过的:
var keys = Object.keys(data);
var result = {};
var numkeys;
for(var i=0; i < keys.length; i++) {
if(!numkeys) {
var numkeys = _.keys(_.pick(data[keys[i]][0], _.isNumber));
}
for(var j=0;j<numkeys.length;j++) {
var sorted = _.sortBy(data['a'], numkeys[j]);
_.forEach(sorted, function(n, k) {
//THIS FAILS
var t = _.set(_.where(data[keys[i]], {keyone: n.keyone}), keys[i]+'rank', k);
console.log(t);
});
}
}
我该怎么做?我的逻辑似乎太复杂了 set
方法并没有按键更新原始对象而是在主对象之后添加了一个新条目。
更新:注意对象 a
重复出现 22
。这会导致分配排名时出现问题,因为 indexOf
将始终 return 第一次出现的索引,因此第二次出现的索引永远不会分配给它,因此该值将是未定义的。
简单来说Javascript:
为了排名,必须以某种方式对数据进行排序。
此解决方案的特点是包含对象的数组以及对 data
中给定对象的引用。然后对所有项目进行排序,原始数据得到它们的 rankgroup
和 rankall
属性.
编辑:现在重复项排名相同。
var data = { a: [{ keyone: 'g', keytwo: 'tina', keythree: 21, keyfour: 15 }, { keyone: 'c', keytwo: 'anna', keythree: 21, keyfour: 15 }, { keyone: 'a', keytwo: 'anna', keythree: 22, keyfour: 15 }, { keyone: 's', keytwo: 'anna', keythree: 10, keyfour: 15 }, { keyone: 'v', keytwo: 'anna', keythree: 7, keyfour: 15 }], b: [{ keyone: 'f', keytwo: 'any', keythree: 45, keyfour: 100 }, { keyone: 'b', keytwo: 'any', keythree: 146, keyfour: 100 }, { keyone: 't', keytwo: 'any', keythree: 23, keyfour: 100 }, { keyone: 'h', keytwo: 'any', keythree: 11, keyfour: 100 }] },
group = {};
Object.keys(data).reduce(function (r, k) {
return r.concat(data[k].map(function (a) {
return { obj: k, ref: a };
}));
}, []).sort(function (a, b) {
return a.ref.keythree - b.ref.keythree || a.ref.keyfour - b.ref.keyfour;
}).forEach(function (a, i, aa) {
if (i && a.ref.keythree === aa[i - 1].ref.keythree && a.ref.keyfour === aa[i - 1].ref.keyfour) {
a.ref.rankgroup = group[a.obj];
a.ref.rankall = group.rankall;
} else {
group[a.obj] = (group[a.obj] || 0) + 1;
group.rankall = (group.rankall || 0) + 1;
a.ref.rankgroup = group[a.obj];
a.ref.rankall = group.rankall;
}
});
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
我就是这样实现的。
将所有keythree
收集到一个数组中并排序(根据index
分配rankall
)。
var all = [];
_.forEach(data, function (a, key) {
_.forEach(a, function(n, k){
all.push(n.keythree);
});
});
all.sort(function(a,b){
return a-b;
});
分配等级
_.forEach(data, function (a, key) {
var sorted = _.sortBy(a, 'keythree');
_.forEach(sorted, function(n, k) {
var index = _.findIndex(data[key], {keyone: n.keyone});
data[key][index]['rankgroup'] = k+1;
data[key][index]['rankall'] = all.indexOf(n.keythree)+1;
});
});
检查这个fiddle
编辑
我正在为骗子创建另一个数组
_.forEach(a, function(n, k) {
if (all.indexOf(n.keythree) !== -1) {
dupes.push(n.keythree);
}
all.push(n.keythree);
});
并获得这些欺骗项目的全球排名
function getGlobalRank(n) {
var val = n.keythree;
if (sorted_dupes[val] === undefined) {
sorted_dupes[val] = [];
_.forEach(data, function(a, key) {
_.forEach(_.where(a, {
keythree: val
}), function(b) {
sorted_dupes[val].push(b);
});
});
sorted_dupes[val] = _.sortByAll(sorted_dupes[val], ['keyfour', 'keytwo', 'keyone']);
}
return _.findIndex(sorted_dupes[val], {
keyone: n.keyone,
keytwo: n.keytwo,
keythree: n.keythree,
keyfour: n.keyfour
}) + 1 + all.indexOf(val);
}
看到项目是根据顺序 keythree
、keyfour
、keytwo
、keyone
中的所有属性排序的(您可以在 _.sortByAll
如果你愿意的话)
代码看起来比我想象的更难看。即将更新重构代码
勾选 fiddle
我有一个像这样的对象数组:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15 },
{ keyone:'s', keytwo: 'anna', keythree: 10, keyfour: 15 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
我想根据 keythree
和 keyfour
的值,在组内以及在整个数据集中为每个对象分配等级。我该怎么做?
更新:我在上面的代码中描述了等级。
结果对象:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15, rankgroup: 3, rankall: 4 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 4, rankall: 5 },
{ keyone:'s', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 2, rankall: 2 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15, rankgroup: 1, rankall: 1 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
我正在使用 lodash
。我的想法是首先根据这些键对数组进行排序,然后遍历原始对象,通过比较另一个键插入排序后的索引。这是我试过的:
var keys = Object.keys(data);
var result = {};
var numkeys;
for(var i=0; i < keys.length; i++) {
if(!numkeys) {
var numkeys = _.keys(_.pick(data[keys[i]][0], _.isNumber));
}
for(var j=0;j<numkeys.length;j++) {
var sorted = _.sortBy(data['a'], numkeys[j]);
_.forEach(sorted, function(n, k) {
//THIS FAILS
var t = _.set(_.where(data[keys[i]], {keyone: n.keyone}), keys[i]+'rank', k);
console.log(t);
});
}
}
我该怎么做?我的逻辑似乎太复杂了 set
方法并没有按键更新原始对象而是在主对象之后添加了一个新条目。
更新:注意对象 a
重复出现 22
。这会导致分配排名时出现问题,因为 indexOf
将始终 return 第一次出现的索引,因此第二次出现的索引永远不会分配给它,因此该值将是未定义的。
简单来说Javascript:
为了排名,必须以某种方式对数据进行排序。
此解决方案的特点是包含对象的数组以及对 data
中给定对象的引用。然后对所有项目进行排序,原始数据得到它们的 rankgroup
和 rankall
属性.
编辑:现在重复项排名相同。
var data = { a: [{ keyone: 'g', keytwo: 'tina', keythree: 21, keyfour: 15 }, { keyone: 'c', keytwo: 'anna', keythree: 21, keyfour: 15 }, { keyone: 'a', keytwo: 'anna', keythree: 22, keyfour: 15 }, { keyone: 's', keytwo: 'anna', keythree: 10, keyfour: 15 }, { keyone: 'v', keytwo: 'anna', keythree: 7, keyfour: 15 }], b: [{ keyone: 'f', keytwo: 'any', keythree: 45, keyfour: 100 }, { keyone: 'b', keytwo: 'any', keythree: 146, keyfour: 100 }, { keyone: 't', keytwo: 'any', keythree: 23, keyfour: 100 }, { keyone: 'h', keytwo: 'any', keythree: 11, keyfour: 100 }] },
group = {};
Object.keys(data).reduce(function (r, k) {
return r.concat(data[k].map(function (a) {
return { obj: k, ref: a };
}));
}, []).sort(function (a, b) {
return a.ref.keythree - b.ref.keythree || a.ref.keyfour - b.ref.keyfour;
}).forEach(function (a, i, aa) {
if (i && a.ref.keythree === aa[i - 1].ref.keythree && a.ref.keyfour === aa[i - 1].ref.keyfour) {
a.ref.rankgroup = group[a.obj];
a.ref.rankall = group.rankall;
} else {
group[a.obj] = (group[a.obj] || 0) + 1;
group.rankall = (group.rankall || 0) + 1;
a.ref.rankgroup = group[a.obj];
a.ref.rankall = group.rankall;
}
});
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
我就是这样实现的。
将所有
keythree
收集到一个数组中并排序(根据index
分配rankall
)。var all = []; _.forEach(data, function (a, key) { _.forEach(a, function(n, k){ all.push(n.keythree); }); }); all.sort(function(a,b){ return a-b; });
分配等级
_.forEach(data, function (a, key) { var sorted = _.sortBy(a, 'keythree'); _.forEach(sorted, function(n, k) { var index = _.findIndex(data[key], {keyone: n.keyone}); data[key][index]['rankgroup'] = k+1; data[key][index]['rankall'] = all.indexOf(n.keythree)+1; }); });
检查这个fiddle
编辑
我正在为骗子创建另一个数组
_.forEach(a, function(n, k) {
if (all.indexOf(n.keythree) !== -1) {
dupes.push(n.keythree);
}
all.push(n.keythree);
});
并获得这些欺骗项目的全球排名
function getGlobalRank(n) {
var val = n.keythree;
if (sorted_dupes[val] === undefined) {
sorted_dupes[val] = [];
_.forEach(data, function(a, key) {
_.forEach(_.where(a, {
keythree: val
}), function(b) {
sorted_dupes[val].push(b);
});
});
sorted_dupes[val] = _.sortByAll(sorted_dupes[val], ['keyfour', 'keytwo', 'keyone']);
}
return _.findIndex(sorted_dupes[val], {
keyone: n.keyone,
keytwo: n.keytwo,
keythree: n.keythree,
keyfour: n.keyfour
}) + 1 + all.indexOf(val);
}
看到项目是根据顺序 keythree
、keyfour
、keytwo
、keyone
中的所有属性排序的(您可以在 _.sortByAll
如果你愿意的话)
代码看起来比我想象的更难看。即将更新重构代码
勾选 fiddle