it-swarm.com.de

Suchen Sie den Index des Objekts im Array mit dem höchsten Wert in der Eigenschaft

Ich habe ein Array mit Objekten:

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

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

Ich habe keine Ahnung, wie viele Objekte sich in meinem Array befinden werden, aber sie haben alle unterschiedliche Werte für ihre Eigenschaften. Ich habe hier nur einige Beispiele aufgeführt.

Frage

Ich muss einen Weg finden, um durch all diese Objekte zu gehen und den Index des Objekts abzurufen, das den höchsten Wert in article.number hat. Wie kann ich das erreichen? Ich darf nur Javascript, jQuery, etc .. keine anderen Sprachen verwenden.

Ich vermute, dass dies die Verwendung von $ .grep und Math.max beinhaltet, aber ich bin festgefahren, ich habe noch nie mit $ .grep gearbeitet.

Zusamenfassend:

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

Es gibt viele Möglichkeiten, dies zu tun, wobei Math.max(), $.grep und $.map nur einige sind. Eine einfache und lesbare Methode, die verständlich sein sollte, besteht darin, das Objekt nur zu iterieren und zu überprüfen, ob der Wert höher ist als eine Variable, falls sie gesetzt ist die Variable zur höheren Zahl:

var highest = 0;

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

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

});

// highest now contains the highest number
14
adeneo

Underscore.js ist eine wunderbare Bibliothek, die Funktionsoperationen für Sammlungen bietet. Eine Lösung in Unterstrich:

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

Obwohl dieses Beispiel ziemlich einfach ist, lassen sich die Operationen gut skalieren. Angenommen, Sie möchten die number -Eigenschaft für jedes Objekt im Array summieren, dessen Text Foo und dessen Farbe red entspricht:

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

Wenn Sie sich überhaupt mit Leistung befassen, ist eine externe Bibliothek sicherlich der richtige Weg. Es gibt eine Vielzahl von Optimierungen, die von externen Bibliotheken bereitgestellt werden können und die in Ihrem eigenen Code nur schwer zu finden sind. Bei einer kleinen Anzahl von Elementen (weniger als einige Tausend) gibt es jedoch keinen nennenswerten Leistungsunterschied zwischen den hier veröffentlichten Antworten. Schwitzen Sie nicht am Benchmarking und verwenden Sie die für Sie verständlichste Antwort.

JSFiddle

11
ljfranklin

Wie wäre es mit:

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

und wenn Sie einen Index brauchen:

index = articles.indexOf(articleWithMaxNumber)

Und für diejenigen, die denken, das Sortieren wäre möglicherweise ein Overkill, um den Maximalwert zu erreichen:

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

Und hier ist ein allgemeiner Ansatz, wie Sie mit map-reduction ein Maximum an Funktionsanwendungen finden:

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

Einige Leute äußerten Bedenken, dass die Methode sort im Vergleich zur iterativen Methode "langsam" sei. Hier ist eine Geige , die beide Methoden verwendet, um ein Array mit 50000 Elementen zu verarbeiten. Die sort-Methode ist auf meinem Computer um ungefähr 50 Millisekunden "langsamer". Hängt von der Anwendung ab, aber in den meisten Fällen ist es nicht wert, darüber zu sprechen.

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

Hier ist eine mögliche Lösung

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]);

On jsfiddle

Hier ist der Leistungstest für die aktuell angegebenen Methoden, können Sie gerne Antworten hinzufügen.

1
Xotic750
array[array.map((o)=>o.number).indexOf(Math.max(...array.map((o)=>o.number)))]

Bedeutet, Element mit Index (i) zu erhalten, wobei (i) der Index der höchsten Zahl ist.

0
Abdennour TOUMI

Ich werde nichts wie Math oder jQuery verwenden, sondern nur das resultierende Array sortieren und das letzte Element entfernen:

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 !

Solange Sie nicht unzählige Artikel in Ihrem Gedächtnis haben, ist dies der schnellste Weg.

0
Axel Amthor
items => 
    items
        .reduce(
            ( highest, item, index ) => 
                item > highest.item 
                    ? { item, index }
                    : highest
        ,   { item: Number.NEGATIVE_INFINITY }
        )
        .index
0
kevin