14

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

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

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

我不知道我的数组中有多少对象,但它们的属性都有不同的值,我只是在这里举了一些例子。

问题

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

我猜这将涉及使用 $.grep 和 Math.max 但我被困住了,我以前从未使用过 $.grep 。

简而言之:

var highestNumber = index of object where article.number is highest
4

7 回答 7

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
于 2013-05-12T15:53:16.100 回答
13

Underscore.js是一个很棒的库,为集合提供函数式操作。下划线的解决方案:

var maxObj = _.max(array, function (obj) {
  return obj.number;
});
var maxIndex = array.indexOf(maxObj);

尽管此示例相当简单,但操作的扩展性很好。假设您想对数组中文本等于Foo且颜色等于的每个对象的 number 属性求和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();  

如果您完全关心性能,那么外部库肯定是要走的路。外部库可以提供大量优化,而这些优化在您自己的代码中是难以匹配的。也就是说,在处理少量项目(少于几千个)时,此处发布的任何答案之间都不会存在明显的性能差异。不要为基准测试而汗流浃背,并使用您最容易理解的答案。

JSFiddle

于 2013-05-12T17:36:12.910 回答
5

怎么样:

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

如果你需要一个索引:

index = articles.indexOf(articleWithMaxNumber)

对于那些认为排序可能是获得最大值的过度杀伤力:

articleWithMaxNumber = articles.reduce(function(max, x) {
    return x.number > max.number ? x : max;
})

下面是一个通用方法,如何使用 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 })

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

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>")

于 2013-05-12T15:53:29.687 回答
1

这是一种可能的解决方案

Javascript

var articles = [],
    howMany = 5,
    i = 0,
    article,
    highest;

while (i < howMany) {
    article = {};
    article.text = "foobar";
    article.color = "red";
    article.number = i;
    articles.push(article);
    i += 1;
}

console.log(articles);

hownMany = articles.length;
i = 0;
while (i < howMany) {
    if (typeof highest !== "number" || articles[i].number > highest) {
        highest = i;
    }

    i += 1;
}

console.log(articles[highest]);

jsfiddle 上

这是当前给定方法的性能测试,请随时添加答案。

于 2013-05-12T15:55:40.813 回答
1
items => 
    items
        .reduce(
            ( highest, item, index ) => 
                item > highest.item 
                    ? { item, index }
                    : highest
        ,   { item: Number.NEGATIVE_INFINITY }
        )
        .index
于 2017-12-08T19:15:18.117 回答
0

我不会使用 Math 或 jQuery 之类的东西,只需对结果数组进行排序并弹出最后一个元素:

var sortArticles = function (a, b)
{
    return ( a.number - b.number ); // should have some type checks ? inverse order: swap a/b
}

articles.sort(sortArticles);


highestArticle = articles.pop(); // or articles[array.length-1]; 
// take care if srticles.length = null !

只要您的记忆中没有大量文章,那是最快的方法。

于 2013-05-12T15:59:07.187 回答
0
array[array.map((o)=>o.number).indexOf(Math.max(...array.map((o)=>o.number)))]

表示获取索引为 (i) 的元素,其中 (i) 是最高数字的索引。

于 2016-08-23T16:56:48.383 回答