864 Stimmen

Wie erhält man unterschiedliche Werte aus einem Array von Objekten in JavaScript?

Angenommen, ich habe die folgenden Daten:

var array = 
    [
        {"name":"Joe", "age":17}, 
        {"name":"Bob", "age":17}, 
        {"name":"Carl", "age": 35}
    ]

Was ist der beste Weg, um in der Lage sein, ein Array aller unterschiedlichen Alter zu erhalten, so dass ich ein Ergebnis-Array von erhalten:

[17, 35]

Gibt es eine Möglichkeit, ich könnte alternativ die Daten oder bessere Methode strukturieren, so dass ich nicht durch jedes Array Überprüfung der Wert von "Alter" und überprüfen Sie gegen ein anderes Array für seine Existenz, und fügen Sie es, wenn nicht zu iterieren würde?

Wenn es eine Möglichkeit gäbe, einfach die verschiedenen Altersstufen herauszufinden, ohne zu iterieren...

Die derzeitige ineffiziente Methode würde ich gerne verbessern... Wenn es bedeutet, dass anstelle von "Array" ein Array von Objekten, sondern eine "Karte" von Objekten mit einigen eindeutigen Schlüssel (z. B. "1,2,3"), das wäre auch okay. Ich bin nur auf der Suche nach dem leistungsfähigsten Weg.

Das Folgende ist, wie ich es derzeit tun, aber für mich, Iteration scheint nur für die Effizienz crummy sein, obwohl es funktioniert ...

var distinct = []
for (var i = 0; i < array.length; i++)
   if (array[i].age not in distinct)
      distinct.push(array[i].age)

23voto

Mrchief Punkte 72978

T forEach Version der Antwort von @travis-j (hilfreich bei modernen Browsern und der Node JS-Welt):

var unique = {};
var distinct = [];
array.forEach(function (x) {
  if (!unique[x.age]) {
    distinct.push(x.age);
    unique[x.age] = true;
  }
});

34% schneller mit Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3

Und eine generische Lösung, die eine Mapper-Funktion benötigt (ein bisschen langsamer als eine direkte Karte, aber das ist zu erwarten):

function uniqueBy(arr, fn) {
  var unique = {};
  var distinct = [];
  arr.forEach(function (x) {
    var key = fn(x);
    if (!unique[key]) {
      distinct.push(key);
      unique[key] = true;
    }
  });
  return distinct;
}

// usage
uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]

17voto

Eevee Punkte 45120

Ich habe angefangen, mich an die Unterstrich in allen neuen Projekten standardmäßig ein, damit ich mir über diese kleinen Datenprobleme keine Gedanken machen muss.

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());

Erzeugt [17, 35] .

14voto

BaM Punkte 519

Es gibt eine andere Möglichkeit, dieses Problem zu lösen:

var result = {};
for(var i in array) {
    result[array[i].age] = null;
}

result = Object.keys(result);

または

result = Object.values(result);

Ich habe keine Ahnung, wie schnell diese Lösung im Vergleich zu den anderen ist, aber ich mag das saubere Aussehen ;-)


EDIT: Okay, die obige Lösung scheint die langsamste von allen zu sein.

Ich habe hier einen Testfall für die Leistung erstellt: http://jsperf.com/distinct-values-from-array

Anstatt auf das Alter (Integer) zu testen, habe ich mich entschieden, die Namen (Strings) zu vergleichen.

Methode 1 (die Lösung von TS) ist sehr schnell. Interessanterweise übertrifft Methode 7 alle anderen Lösungen, hier habe ich nur die .indexOf() und eine "manuelle" Implementierung verwendet, die den Aufruf von Funktionen in Schleifen vermeidet:

var result = [];
loop1: for (var i = 0; i < array.length; i++) {
    var name = array[i].name;
    for (var i2 = 0; i2 < result.length; i2++) {
        if (result[i2] == name) {
            continue loop1;
        }
    }
    result.push(name);
}

Der Leistungsunterschied zwischen Safari und Firefox ist erstaunlich, und es scheint, dass Chrome die beste Optimierungsarbeit leistet.

Ich bin mir nicht ganz sicher, warum die obigen Schnipsel im Vergleich zu den anderen so schnell sind, vielleicht hat jemand, der klüger ist als ich, eine Antwort ;-)

14voto

Boanerges Punkte 695
const array =
  [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
  ]

const key = 'age';

const arrayUniqueByKey = [...new Map(array.map(item =>
  [item[key], item])).values()];

console.log(arrayUniqueByKey);

11voto

Jaison James Punkte 3982
var array = [
          {"name":"Joe", "age":17}, 
          {"name":"Bob", "age":17}, 
          {"name":"Carl", "age": 35}
      ];

      const ages = [...new Set(array.reduce((a, c) => [...a, c.age], []))];

      console.log(ages);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X