繁体   English   中英

获取JavaScript数组中每个键的最大值

[英]Get max value per key in a javascript array

说,我有以下数组:

[ 
  {a:1, b:"apples"}, 
  {a:3, b:"apples"}, 
  {a:4, b:"apples"}, 
  {a:1, b:"bananas"}, 
  {a:3, b:"bananas"}, 
  {a:5, b:"bananas"}, 
  {a:6, b:"bananas"}, 
  {a:3, b:"oranges"}, 
  {a:5, b:"oranges"}, 
  {a:6, b:"oranges"}, 
  {a:10, b:"oranges"} 
]

我想为每种类型的“ b”有效地获得具有最高a的整个对象,因此我的函数应产生:

[
  {a:4, b:"apples"},
  {a:6, b:"bananas"},
  {a:10, b:"oranges"}
]

现在,我将执行以下操作:

var cache = {};
var resultobj = {};
result = [];
array.forEach(function (r) {
 if (cache[r.b] && cache[r.b] > r.a) {
   result[r.b] = r;
 }
})
for (var key in result) {
 result.push(result[key]);
}

看起来很糟糕,效率低下...?

在ES5中是两线,而在ES6中是一线:

 ary = [ {a: 0, b:"apples"}, {a:-3, b:"apples"}, {a:-4, b:"apples"}, {a:1, b:"bananas"}, {a:3, b:"bananas"}, {a:5, b:"bananas"}, {a:6, b:"bananas"}, {a:3, b:"oranges"}, {a:5, b:"oranges"}, {a:6, b:"oranges"}, {a:10, b:"oranges"} ] // ES5 maxes = {}; ary.forEach(function(e) { maxes[eb] = eb in maxes ? Math.max(maxes[eb], ea) : ea; }); document.write('<pre>'+JSON.stringify(maxes,0,3)); // ES6 maxes = ary.reduce((m, e) => Object.assign(m, { [eb]: eb in m ? Math.max(m[eb], ea) : ea }), {}); document.write('<pre>'+JSON.stringify(maxes,0,3)); 

您可以尝试如下操作:

逻辑:

  • 遍历数组
  • 检查值是否存在于最后一个元素中。 假设:数据基于b排序 )。
  • 如果找到匹配项则替换,否则将其推送。

 var data = [ {a:1, b:"apples"}, {a:3, b:"apples"}, {a:4, b:"apples"}, {a:1, b:"bananas"}, {a:3, b:"bananas"}, {a:5, b:"bananas"}, {a:6, b:"bananas"}, {a:3, b:"oranges"}, {a:5, b:"oranges"}, {a:6, b:"oranges"}, {a:10, b:"oranges"} ] var distinctB = data.slice(0,1); data.forEach(function(o){ if(distinctB[distinctB.length-1] && ob !== distinctB[distinctB.length-1].b){ distinctB.push(o); } else{ distinctB[distinctB.length-1] = o; } }); document.write("<pre>" + JSON.stringify(distinctB,0,4) + "</pre>"); 

它在对象的索引的帮助下起作用。

 var data = [{ a: 1, b: "apples" }, { a: 3, b: "apples" }, { a: 4, b: "apples" }, { a: 1, b: "bananas" }, { a: 3, b: "bananas" }, { a: 5, b: "bananas" }, { a: 6, b: "bananas" }, { a: 3, b: "oranges" }, { a: 5, b: "oranges" }, { a: 6, b: "oranges" }, { a: 10, b: "oranges" }], result = function (array) { var r = [], o = {}; array.forEach(function (a) { if (!(ab in o)) { o[ab] = r.push(a) - 1; return; } if (r[o[ab]].a < aa) { r[o[ab]] = a; } }); return r; }(data); document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>'); 

您接近了,代码中有一些错误的逻辑,您已经声明了cache ,但是没有使用过它。

if (cache[r.b] && cache[r.b] > r.a) //This always will be "false"

参见工作示例

 var array = [ { a: 1, b: "apples" }, { a: 3, b: "apples" }, { a: 4, b: "apples" }, { a: 1, b: "bananas" }, { a: 3, b: "bananas" }, { a: 5, b: "bananas" }, { a: 6, b: "bananas" }, { a: 3, b: "oranges" }, { a: 5, b: "oranges" }, { a: 6, b: "oranges" }, { a: 10, b: "oranges" } ]; var cache = {}; array.forEach(function(e) { var t = cache[eb]; if (t) { ta = ta > ea ? ta : ea; } else { cache[eb] = e; } }); var res = Object.keys(cache).map(e => cache[e]); document.write(JSON.stringify(res)); 

确实,如果您的水果名称将唯一,那么最好的数据结构是对象而不是对象数组。

var out = arr.reduce(function (p, c) {
  var key = c.b;
  p[key] = p[key] || 0;
  if (c.a > p[key]) p[key] = c.a;
  return p;
}, {}); // { apples: 4, bananas: 6, oranges: 10 }

演示

Array.foreachMath.max方法的简短解决方案:

var map = {},result = [];

obj.forEach(function(v){
   (!(v['b'] in map)) ? map[v['b']] = [v['a']] : map[v['b']].push(v['a']);
});
for (var prop in map) {
    result.push({a: Math.max.apply(null, map[prop]), b: prop});
}

console.log(result);
// the output:
[
  {a:4, b:"apples"},
  {a:6, b:"bananas"},
  {a:10, b:"oranges"}
]

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/max

您正在结果result[rb] = r;中设置值result[rb] = r; 但比较中的值cache通过这样做if (cache[rb] && cache[rb] > ra) {

您需要在cache而不是result设置值,然后针对预期结果迭代cache

将forEach和for循环替换为

array.forEach(function (r) {
 if (cache[r.b] && cache[r.b] > r.a) {
   cache[r.b] = r.a;
 }
});
for (var key in cache) 
{
 result.push(result[key]);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM