Wie erhalte ich einen Index des Objekts anhand seiner Eigenschaft in JavaScript?

239

Zum Beispiel habe ich:

var Data = [
  { id_list: 1, name: 'Nick', token: '312312' },
  { id_list: 2, name: 'John', token: '123123' },
]

Dann möchte ich dieses Objekt zum Beispiel sortieren / umkehrenname . Und dann möchte ich so etwas bekommen:

var Data = [
  { id_list: 2, name: 'John', token: '123123' },
  { id_list: 1, name: 'Nick', token: '312312' },
]

Und jetzt möchte ich den Index des Objekts mit der Eigenschaft kennen name='John', um den Wert des Eigenschaftstokens zu erhalten.

Wie löse ich das Problem?

Rsboarder
quelle
Warum möchten Sie die Liste zuerst sortieren, bevor Sie nach der Immobilie suchen?
JJJ
JavaScript-Objekte sind {Key:Value}, ich habe es für Sie behoben.
Rocket Hazmat
Wenn Sie die Antworten durchsuchen, scheint ein natives DataObjekt vorhanden zu sein. Es handelt sich lediglich um einen großgeschriebenen Variablennamen, der gegen die Konvention verstößt. Wenn jemand anderes davon betroffen ist, werde ich die Frage und die Antworten bearbeiten, um diese Benennung zu korrigieren.
Roy Prins
Verwandte Frage: stackoverflow.com/questions/10557486/…
Anton Tarasenko

Antworten:

170

Wie die anderen Antworten vermuten lassen, ist das Durchlaufen des Arrays wahrscheinlich der beste Weg. Aber ich würde es in seine eigene Funktion stellen und es etwas abstrakter machen:

function findWithAttr(array, attr, value) {
    for(var i = 0; i < array.length; i += 1) {
        if(array[i][attr] === value) {
            return i;
        }
    }
    return -1;
}

var Data = [
    {id_list: 2, name: 'John', token: '123123'},
    {id_list: 1, name: 'Nick', token: '312312'}
];

Damit können Sie nicht nur herausfinden, welches 'John' enthält, sondern auch, welches das Token '312312' enthält:

findWithAttr(Data, 'name', 'John'); // returns 0
findWithAttr(Data, 'token', '312312'); // returns 1
findWithAttr(Data, 'id_list', '10'); // returns -1

BEARBEITEN: Die Funktion wurde aktualisiert und gibt -1 zurück, wenn sie nicht gefunden wird. Sie folgt demselben Konstrukt wie Array.prototype.indexOf ()

Chris Pickett
quelle
1
Es wurde eine Antwort hinzugefügt, die diese erweitert, um die Suche tiefer als eine Attributebene abzudecken. Danke für diesen Chris - hat wirklich geholfen: D
Ed Shee
3
Beachten Sie für diejenigen, die Probleme mit dieser Lösung haben, dass das Gleichheitszeichen === nicht nur den Wert, sondern auch den Datentyp überprüft. Wenn Sie also Datum, Zahlen und leere Werte vergleichen, wird möglicherweise false zurückgegeben, wenn der tatsächliche Wert eine Zeichenfolge ist. Sie können das Gleichheitszeichen == verwenden, wenn der Datentyp für Sie nicht wesentlich ist.
David Addoteye
TUN SIE DAS NICHT. Erfahren Sie, wie Sie Funktionen höherer Ordnung verwenden. Dies ist die alte Vorgehensweise.
Led
325

Da ist der Sortierteil schon beantwortet. Ich werde nur einen anderen eleganten Weg vorschlagen, um den Index einer Eigenschaft in Ihrem Array zu erhalten

Ihr Beispiel ist:

var Data = [
    {id_list:1, name:'Nick',token:'312312'},
    {id_list:2,name:'John',token:'123123'}
]

Du kannst tun:

var index = Data.map(function(e) { return e.name; }).indexOf('Nick');

Array.prototype.mapist auf IE7 oder IE8 nicht verfügbar. ES5-Kompatibilität

Und hier ist es mit ES6 und Pfeilsyntax, was noch einfacher ist:

const index = Data.map(e => e.name).indexOf('Nick');
Deutscher Attanasio
quelle
4
Ich muss das gesamte Array iterieren, egal was passiert. Die erste Methode muss nicht.
Deutsch Attanasio
1
Einfach, aber berücksichtigen Sie die Leistung bei der Verwendung großer
Datenmengen
1
Wirklich tolle Antwort hat mir bei diesem Problem geholfen!
NiallMitch14
1
Diese Lösung ist sehr schön. Mögen Sie tausend Jahre alt werden, Sir.
deepelement
3
Wenn Sie in der ES6-Version eine Map und dann indexOf erstellen, werden die Arrays zweimal durchlaufen. Stattdessen sollten Sie die findIndex-Methode verwenden, die in meiner Antwort gezeigt wird
silverlight513
208

Wenn Sie mit ES6 gut zurechtkommen. Arrays haben jetzt die Funktion findIndex . Was bedeutet, dass Sie so etwas tun können:

const index = Data.findIndex(item => item.name === 'John');
silverlight513
quelle
6
Zweifellos die direkteste und eleganteste Lösung, ich würde eine kleine nicht machen, dass findIndex gierig ist - in meinem Fall war das perfekt -, aber Benutzer sind sich bewusst, dass wenn Sie Objekte mit doppelten Werten haben (dh zwei Objekte mit name: John), dies nur zurückgibt das erste Match
GrayedFox
Genial!! Danke dir.
moreirapontocom
@GrayedFox meintest du nicht NICHT gierig? Gierig bedeutet mehr Ergebnisse und findIndex gibt nur die erste Übereinstimmung zurück.
Jos
1
Sorry @Jos, aber ich denke du verstehst nicht ganz was ein gieriger Suchalgorithmus macht . Ein gieriger Algorithmus berücksichtigt nur die verfügbaren Informationen. Dies ist rechnerisch effizient, um beispielsweise nach einem Element in einer Liste zu suchen, wenn Sie nur ein Ergebnis benötigen. Die findIndex-Methode ist genau richtig, da sie nur die erste Übereinstimmung zurückgibt. Wenn es nicht gierig wäre, würde es weiter suchen. Sie denken an den Begriff "gierig", wie er im alltäglichen Englisch verwendet wird, aber im Kontext der Programmierung (dh SO) ist es das Gegenteil von dem, was Sie denken;)
GrayedFox
Vielen Dank für die Erklärung von @GrayedFox. Mein Hinweis auf gierig stammte eigentlich auch aus der Programmierung, bezog sich aber auf reguläre Ausdrücke, bei denen gierig mehr Zeichen als nicht gierig sind! :-)
Jos
28
var index = Data.findIndex(item => item.name == "John")

Welches ist eine vereinfachte Version von:

var index = Data.findIndex(function(item){ return item.name == "John"})

Von mozilla.org:

Die Methode findIndex () gibt den Index des ersten Elements im Array zurück, das die bereitgestellte Testfunktion erfüllt. Andernfalls wird -1 zurückgegeben.

edank
quelle
2
Verwenden Sie "===" für den Zeichenfolgenvergleich. Dies ist das einzige, was in dieser Antwort fehlt.
Bruno Tavares
@BrunoTavares, welches Szenario wäre Ihrer Meinung nach in diesem Fall anders?
Edank
1
@edank Wenn OP das tokenFeld anstelle des nameFeldes überprüft, kann es zu Problemen kommen, da es Data[0].token == 312312ausgewertet wird true, aber Data[0].token === 321321ausgewertet wird false.
Kem
@edank werfen Sie einen Blick in diese Antwort stackoverflow.com/questions/359494/…
Bruno Tavares
23

Wenn Sie Probleme mit dem Internet Explorer haben, können Sie die Funktion map () verwenden, die ab 9.0 unterstützt wird:

var index = Data.map(item => item.name).indexOf("Nick");
Alain T.
quelle
1
Die Antwort unten enthält weitere Informationen und wurde zuerst veröffentlicht.
Alexander
Dies ist definitiv die beste Lösung dafür.
Bebolicious
4

Der einzige für mich bekannte Weg ist das Durchlaufen aller Arrays:

var index=-1;
for(var i=0;i<Data.length;i++)
  if(Data[i].name==="John"){index=i;break;}

oder Groß- und Kleinschreibung nicht beachten:

var index=-1;
for(var i=0;i<Data.length;i++)
  if(Data[i].name.toLowerCase()==="john"){index=i;break;}

Auf Ergebnisvariable Index enthält Index des Objekts oder -1 , wenn nicht gefunden.

Andrew D.
quelle
2

ein prototypischer Weg

(function(){
  if (!Array.prototype.indexOfPropertyValue){
    Array.prototype.indexOfPropertyValue = function(prop,value){
      for (var index = 0; index < this.length; index++){
        if (this[index][prop]){
          if (this[index][prop] == value){
            return index;
          }
        }
      }
      return -1;
    }
  }
 })();
 // usage:
 var Data = [
 {id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}];
 Data.indexOfPropertyValue('name','John'); // returns 1 (index of array);
 Data.indexOfPropertyValue('name','Invalid name') // returns -1 (no result);
 var indexOfArray = Data.indexOfPropertyValue('name','John');
 Data[indexOfArray] // returns desired object.
Patrik Wallin
quelle
Ich musste dies ein wenig ändern, um meiner Situation gerecht zu werden. Ich suchte nach dem Index einer Eigenschaft mit dem Wert null, und in der fünften Zeile wurde dieser Index übersprungen.
David Brunow
1

Sie können Array.sort mit einer benutzerdefinierten Funktion als Parameter verwenden, um Ihren Sortiermechanismus zu definieren.

In Ihrem Beispiel würde es geben:

var Data = [
    {id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]

Data.sort(function(a, b){
    return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
});

alert("First name is : " + Data[0].name); // alerts 'John'
alert("Second name is : " + Data[1].name); // alerts 'Nick'

Die Sortierfunktion muss entweder -1 zurückgeben, wenn a vor b stehen soll, 1, wenn a nach b kommen soll, und 0, wenn beide gleich sind. Es liegt an Ihnen, die richtige Logik in Ihrer Sortierfunktion zu definieren, um das Array zu sortieren.

Bearbeiten: Verpasste den letzten Teil Ihrer Frage, in dem Sie den Index wissen möchten. Sie müssten das Array durchlaufen, um herauszufinden, wie andere gesagt haben.


quelle
1

Gehen Sie einfach Ihr Array durch und finden Sie die Position:

var i = 0;
for(var item in Data) {
    if(Data[item].name == 'John')
        break;
    i++;
}
alert(i);
Sascha Galeere
quelle
Das sollte sein if(Data[item].name == 'John'), ich habe es für dich repariert.
Rocket Hazmat
Das hat einen Moment Zeit. Wenn der Variable 'nicht gefunden' i enthalten positiven Index. Und um 'nicht gefunden' zu testen, muss verglichen werden, ob i === Data.length
Andrew D.
Der zweite Moment ist, wenn das Array benutzerdefinierte Nicht-Indexer-Eigenschaften enthält. Zum Beispiel: var Data [1,2,3,4,5]; Daten ["Test"] = 7897; Vergleichen Sie die Ausgabe von: for (var i in Data) alert (Data [i]); und für (var i = 0; i <Data.length; i ++) alert (Data [i]);
Andrew D.
1

Warum benutzt du kein kleines Workaround?

Erstellen Sie ein neues Array mit Namen als Indizes. Danach werden bei allen Suchvorgängen Indizes verwendet. Also nur eine Schleife. Danach müssen Sie nicht alle Elemente durchlaufen!

var Data = [
    {id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
    ]
var searchArr = []
Data.forEach(function(one){
  searchArr[one.name]=one;
})
console.log(searchArr['Nick'])

http://jsbin.com/xibala/1/edit

Live-Beispiel.


quelle
Das bedeutet, zuerst alles zu durchlaufen ... und dann Objekte zu ändern (es sei denn, Sie klonen sie, aber das ist noch mehr Aufwand). Und danach schleifen Sie erneut (zumindest teilweise).
Jos
1

Die Antwort von Chris Pickett wurde erweitert, da ich in meinem Fall tiefer als eine Attributebene suchen musste:

function findWithAttr(array, attr, value) {
  if (attr.indexOf('.') >= 0) {
    var split = attr.split('.');
    var attr1 = split[0];
    var attr2 = split[1];
    for(var i = 0; i < array.length; i += 1) {
      if(array[i][attr1][attr2] === value) {
        return i;
      }
    }
  } else {
    for(var i = 0; i < array.length; i += 1) {
      if(array[i][attr] === value) {
        return i;
      }
    }
  };
};

Sie können 'attr1.attr2' an die Funktion übergeben

Ed Shee
quelle
1

Was ist damit? ::

Data.indexOf(_.find(Data, function(element) {
  return element.name === 'John';
}));

Angenommen, Sie verwenden lodash oder Unterstriche.

Ellone
quelle
1
var fields = {
teste:
{
    Acess:
    {
        Edit: true,
      View: false

      }
 },
teste1:
{
    Acess:
    {
        Edit: false,
      View: false

      }
  }
};

console.log(find(fields,'teste'));
function find(fields,field){
    for(key in fields){
        if(key == field){
        return true;
    }
}
return false;
}

Wenn Sie ein Objekt mit mehreren Objekten haben und wissen möchten, ob ein Objekt im Master-Objekt enthalten ist, geben Sie einfach find (MasterObject, 'Object to Search') ein. Diese Funktion gibt die Antwort zurück, falls vorhanden oder nicht (TRUE oder FALSE) ), Ich hoffe Hilfe dabei, kann das Beispiel auf JSFiddle sehen .

Pedro Monteiro Arantes
quelle
Fügen Sie eine Erklärung mit Antwort hinzu, wie diese Antwort OP bei der Behebung des aktuellen Problems
hilft
@ ρяσsρєяK, Danke für Ihren Vorschlag, ich füge bereits die Erklärung hinzu :)
Pedro Monteiro Arantes
1
let indexOf = -1;
let theProperty = "value"
let searchFor = "something";

theArray.every(function (element, index) {

    if (element[theProperty] === searchFor) {
        indexOf = index;
        return false;
    }
    return true;
});
Itay Merchav
quelle
1
collection.findIndex(item => item.value === 'smth') !== -1
Eugene Lyzo
quelle
Während dieses Code-Snippet die Frage lösen kann, hilft das Hinzufügen einer Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen. Bitte versuchen Sie auch, Ihren Code nicht mit erklärenden Kommentaren zu überfüllen, da dies die Lesbarkeit sowohl des Codes als auch der Erklärungen beeinträchtigt!
Auf Wiedersehen StackExchange
1

Wenn Sie den Wert des Eigenschaftstokens abrufen möchten, können Sie dies auch versuchen

    let data=[
      { id_list: 1, name: 'Nick', token: '312312' },
      { id_list: 2, name: 'John', token: '123123' },
    ]

    let resultingToken =  data[_.findKey(data,['name','John'])].token

Dabei ist _.findKey die Funktion eines Lodash

Akash Singh
quelle
0

Alternativ zur Antwort von Deutsch Attanasio Ruiz können Sie die 2. Schleife entfernen, indem Sie Array.reduce () anstelle von Array.map () verwenden.

var Data = [
    { name: 'hypno7oad' }
]
var indexOfTarget = Data.reduce(function (indexOfTarget, element, currentIndex) {
    return (element.name === 'hypno7oad') ? currentIndex : indexOfTarget;
}, -1);
hypno7oad
quelle
-1

Unterstrich verwenden:

var index = _.indexOf(_.pluck(item , 'name'), 'Nick');
M Faisal Hameed
quelle