查找属性中具有最高值的数组中的对象索引

Rij*_*oek 11 javascript arrays jquery object

我有一个包含对象的数组:

var articles = [];
var article = {};

Simple loop that iterates x times {
        article.text = "foobar";
        article.color = "red";
        article.number = 5;
        articles.push(article);
}
Run Code Online (Sandbox Code Playgroud)

我不知道我的数组中会有多少个对象,但它们的属性都有不同的值,我在这里给出了一些例子.

我需要找到一种方法来遍历所有这些对象并检索article.number中具有最高值的对象的索引.我怎样才能做到这一点?我可能只使用javascript,jQuery等.没有其他语言.

我猜这将涉及同时使用$ .grep和Math.max但是我被卡住了,我以前从未使用$ .grep.

简而言之:

var highestNumber = index of object where article.number is highest
Run Code Online (Sandbox Code Playgroud)

ade*_*neo 14

有很多方法可以做到这一点,Math.max(),$.grep$.map是少数,但一个简单易读的方法,应该是可以理解的是,只是重复的对象,并检查值大于变量更高,如果是,设置变量数字越大:

var highest = 0;

$.each(articles, function(key, article) {

    if (article.number > highest) highest = article.number;

});

// highest now contains the highest number
Run Code Online (Sandbox Code Playgroud)

  • 注意:`$ .each`看起来很慢.手动编写的`while`或`for`循环将迭代得更快. (2认同)

小智 11

Underscore.js是一个很棒的库,可以为集合提供功能操作.下划线的解决方案:

var maxObj = _.max(array, function (obj) {
  return obj.number;
});
var maxIndex = array.indexOf(maxObj);
Run Code Online (Sandbox Code Playgroud)

虽然这个例子非常简单,但操作规模很好.假设您想要对数组中每个对象的数字属性求和,其中文本等于Foo和颜色等于red:

var customSum = _.chain(array)
  .where({ 
    text: "Foo", color: "red"
  })
  .map(function(obj) {
    return obj.number; 
  })
  .reduce(function(memo, num) {
    return memo + num;
  }, 0)
  .value();  
Run Code Online (Sandbox Code Playgroud)

如果您完全关注性能,那么外部库肯定是可行的方法.外部库可以提供大量的优化,这些优化很难在您自己的代码中匹配.也就是说,当处理少量项目(少于几千个)时,这里发布的任何答案之间都不会有明显的性能差异.不要冒出基准测试并使用对您来说最容易理解的答案.

的jsfiddle

  • 如果你正在使用Lodash,`_.maxBy`是一个易于使用的替代ljfranklin的方法.https://lodash.com/docs#maxBy (2认同)

geo*_*org 5

怎么样:

articleWithMaxNumber = articles.slice(0).sort(
     function(x, y) { return y.number - x.number })[0]
Run Code Online (Sandbox Code Playgroud)

如果你需要一个索引:

index = articles.indexOf(articleWithMaxNumber)
Run Code Online (Sandbox Code Playgroud)

对于那些认为排序可能是一个过度杀手来获得最大值的人:

articleWithMaxNumber = articles.reduce(function(max, x) {
    return x.number > max.number ? x : max;
})
Run Code Online (Sandbox Code Playgroud)

以下是如何使用map-reduce查找最多函数应用程序的通用方法:

function maxBy(array, fn) {
    return array.map(function(x) {
        return [x, fn(x)]
    }).reduce(function(max, x) {
        return x[1] > max[1] ? x : max;
    })[0]
}

articleWithMaxNumber = maxBy(articles, function(x) { return x.number })
Run Code Online (Sandbox Code Playgroud)

sort与迭代的方法相比,有些人对这种方法"缓慢" 提出了担忧.这是一个小提琴,它使用两种方法处理一个包含50000个项目的数组.我的机器上的sort方法"慢"约50毫秒.取决于应用程序,但在大多数情况下,这不值得讨论.

var articles = [];
var len = 50000;

while (len--) {
  var article = {};
  article.text = "foobar";
  article.color = "red";
  article.number = Math.random();
  articles.push(article);
}

d = performance.now();
max1 = articles.slice(0).sort(
  function(x, y) {
    return y.number - x.number
  })[0]
time1 = performance.now() - d

d = performance.now();
max2 = articles.reduce(function(max, x) {
  return x.number > max.number ? x : max;
})
time2 = performance.now() - d

document.body.innerHTML = [time1, time2].join("<br>")
Run Code Online (Sandbox Code Playgroud)

  • 是.这是无法实现的.虽然这是一个简单的解决方案,但至少应该表明它可能不是最好的. (3认同)
  • 排序最多是"O(n log n)",而搜索是"O(n)".肯定会有一个交叉点,但是Bergi是对的,你永远不应该排序数组只是为了找到它的最大值.问题是,你事先并不知道那个交叉的地方,但留下一个没有挑战的基于排序的答案不是一个选择. (3认同)
  • @ thg435重点是,_没有人确切知道_虽然数字应该是"相对较低".它的实现和数据依赖.对于小数据集,时序差异无关紧要,因此请使用其中之一.对于大型数据集,差异非常重要,因此使用线性搜索.因此,如果数据集未知,请使用线性搜索. (2认同)