Angenommen, ich habe ein Objekt:
[
{
'title': "some title"
'channel_id':'123we'
'options': [
{
'channel_id':'abc'
'image':'http://asdasd.com/all-inclusive-block-img.jpg'
'title':'All-Inclusive'
'options':[
{
'channel_id':'dsa2'
'title':'Some Recommends'
'options':[
{
'image':'http://www.asdasd.com' 'title':'Sandals'
'id':'1'
'content':{
...
Ich möchte das eine Objekt finden, bei dem die ID 1 ist. Gibt es eine Funktion für so etwas? Ich könnte die _.filter
Methode von Underscore verwenden, aber ich müsste oben beginnen und nach unten filtern.
javascript
underscore.js
Harry
quelle
quelle
Was für mich funktioniert hat, war dieser faule Ansatz, nicht algorithmisch faul;)
if( JSON.stringify(object_name).indexOf("key_name") > -1 ) { console.log("Key Found"); } else{ console.log("Key not Found"); }
quelle
if( JSON.stringify(object_name).indexOf('{"key_name":') > -1 ) {
einschließlich der linken geschweiften Klammer, doppelter Anführungszeichen und des Doppelpunkts, den JSON.stringify hinzufügt? Ich denke, es könnte eine nette Überprüfung sein, um sicherzustellen, dass der Schlüsselname tatsächlich ein Schlüssel ist und nicht irgendwie im "Wert" -Teil.JSON.stringify(object).includes(text)
Wenn Sie das erste Element erhalten möchten, dessen ID 1 ist, während das Objekt durchsucht wird, können Sie diese Funktion verwenden:
function customFilter(object){ if(object.hasOwnProperty('id') && object["id"] == 1) return object; for(var i=0; i<Object.keys(object).length; i++){ if(typeof object[Object.keys(object)[i]] == "object"){ var o = customFilter(object[Object.keys(object)[i]]); if(o != null) return o; } } return null; }
Wenn Sie alle Elemente erhalten möchten, deren ID 1 ist, dann (alle Elemente, deren ID 1 ist, werden im Ergebnis gespeichert, wie Sie sehen):
function customFilter(object, result){ if(object.hasOwnProperty('id') && object.id == 1) result.push(object); for(var i=0; i<Object.keys(object).length; i++){ if(typeof object[Object.keys(object)[i]] == "object"){ customFilter(object[Object.keys(object)[i]], result); } } }
quelle
Eine andere (etwas alberne) Option besteht darin, die natürlich rekursive Natur von auszunutzen
JSON.stringify
und ihm eine Ersetzungsfunktion zu übergeben, die während des Stringifizierungsprozesses für jedes verschachtelte Objekt ausgeführt wird:const input = [{ 'title': "some title", 'channel_id': '123we', 'options': [{ 'channel_id': 'abc', 'image': 'http://asdasd.com/all-inclusive-block-img.jpg', 'title': 'All-Inclusive', 'options': [{ 'channel_id': 'dsa2', 'title': 'Some Recommends', 'options': [{ 'image': 'http://www.asdasd.com', 'title': 'Sandals', 'id': '1', 'content': {} }] }] }] }]; console.log(findNestedObj(input, 'id', '1')); function findNestedObj(entireObj, keyToFind, valToFind) { let foundObj; JSON.stringify(input, (_, nestedValue) => { if (nestedValue && nestedValue[keyToFind] === valToFind) { foundObj = nestedValue; } return nestedValue; }); return foundObj; };
quelle
throw
. jsfiddle.net/w4vs36hmIch habe diese Seite durch googeln nach ähnlichen Funktionen gefunden. Basierend auf der Arbeit von Zach und regulärmike habe ich eine andere Version erstellt, die meinen Bedürfnissen entspricht.
Übrigens, Teriffic Work Zah und Regularmike! Ich werde den Code hier posten:
function findObjects(obj, targetProp, targetValue, finalResults) { function getObject(theObject) { let result = null; if (theObject instanceof Array) { for (let i = 0; i < theObject.length; i++) { getObject(theObject[i]); } } else { for (let prop in theObject) { if(theObject.hasOwnProperty(prop)){ console.log(prop + ': ' + theObject[prop]); if (prop === targetProp) { console.log('--found id'); if (theObject[prop] === targetValue) { console.log('----found porop', prop, ', ', theObject[prop]); finalResults.push(theObject); } } if (theObject[prop] instanceof Object || theObject[prop] instanceof Array){ getObject(theObject[prop]); } } } } } getObject(obj); }
Was sie tut , ist es , jedes Objekt innerhalb von findet
obj
mit Eigenschaftsnamen und WertanpassungtargetProp
undtargetValue
und es wird auf den Push -finalResults
Array. Und hier ist die jsfiddle zum Herumspielen: https://jsfiddle.net/alexQch/5u6q2ybc/quelle
return
dasfinalResults
Array verwendet wird, anstatt eine andere Variable als Eingabe zum Schreiben zu akzeptierenIch habe zu diesem Zweck eine Bibliothek erstellt: https://github.com/dominik791/obj-traverse
Sie können folgende
findFirst()
Methode verwenden:var foundObject = findFirst(rootObject, 'options', { 'id': '1' });
Und jetzt
foundObject
speichert die Variable einen Verweis auf das gesuchte Objekt.quelle
Verbesserte @ haitaka-Antwort mit Schlüssel und Prädikat
function deepSearch (object, key, predicate) { if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object for (let i = 0; i < Object.keys(object).length; i++) { let value = object[Object.keys(object)[i]]; if (typeof value === "object" && value != null) { let o = deepSearch(object[Object.keys(object)[i]], key, predicate) if (o != null) return o } } return null }
Dies kann also wie folgt aufgerufen werden:
var result = deepSearch(myObject, 'id', (k, v) => v === 1);
oder
var result = deepSearch(myObject, 'title', (k, v) => v === 'Some Recommends');
Hier ist die Demo: http://jsfiddle.net/a21dx6c0/
BEARBEITET
Auf die gleiche Weise können Sie mehr als ein Objekt finden
function deepSearchItems(object, key, predicate) { let ret = []; if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) { ret = [...ret, object]; } if (Object.keys(object).length) { for (let i = 0; i < Object.keys(object).length; i++) { let value = object[Object.keys(object)[i]]; if (typeof value === "object" && value != null) { let o = this.deepSearchItems(object[Object.keys(object)[i]], key, predicate); if (o != null && o instanceof Array) { ret = [...ret, ...o]; } } } } return ret; }
quelle
typeof null === 'object'
Wenn also Werte im Objekt null sind, stürzt die Funktion ab, wenn versucht wird, sie zu wiederholen. Sie sollten daher auch die Richtigkeit überprüfen, bevor Sie eine Rekursion durchführen.@Iulian Pinzarus Antwort war fast genau das, was ich brauchte, aber es funktioniert nicht, wenn Ihre Objekte Nullwerte haben. Diese Version behebt das.
function deepSearch (object, key, predicate) { if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object for (let i = 0; i < Object.keys(object).length; i++) { const nextObject = object[Object.keys(object)[i]]; if (nextObject && typeof nextObject === "object") { let o = deepSearch(nextObject, key, predicate) if (o != null) return o } } return null }
quelle
Ich würde versuchen, das Rad nicht neu zu erfinden. Wir verwenden den Objekt-Scan für alle unsere Datenverarbeitungsanforderungen. Es ist konzeptionell sehr einfach, erlaubt aber viele coole Sachen. So würden Sie Ihre spezifische Frage lösen
const objectScan = require('object-scan'); const find = (id, input) => objectScan(['**'], { abort: true, rtn: 'value', filterFn: ({ value }) => value.id === id })(input); const data = [{ title: 'some title', channel_id: '123we', options: [{ channel_id: 'abc', image: 'http://asdasd.com/all-inclusive-block-img.jpg', title: 'All-Inclusive', options: [{ channel_id: 'dsa2', title: 'Some Recommends', options: [{ image: 'http://www.asdasd.com', title: 'Sandals', id: '1', content: {} }] }] }] }]; console.log(find('1', data)); // => { image: 'http://www.asdasd.com', title: 'Sandals', id: '1', content: {} }
quelle
Verbesserte Antwort zur Berücksichtigung von Zirkelverweisen innerhalb von Objekten. Es zeigt auch den Weg an, den es genommen hat, um dorthin zu gelangen.
In diesem Beispiel suche ich nach einem Iframe, von dem ich weiß, dass er sich irgendwo in einem globalen Objekt befindet:
const objDone = [] var i = 2 function getObject(theObject, k) { if (i < 1 || objDone.indexOf(theObject) > -1) return objDone.push(theObject) var result = null; if(theObject instanceof Array) { for(var i = 0; i < theObject.length; i++) { result = getObject(theObject[i], i); if (result) { break; } } } else { for(var prop in theObject) { if(prop == 'iframe' && theObject[prop]) { i--; console.log('iframe', theObject[prop]) return theObject[prop] } if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) { result = getObject(theObject[prop], prop); if (result) { break; } } } } if (result) console.info(k) return result; }
Ausführen der folgenden:
getObject(reader, 'reader')
gab die folgende Ausgabe und das iframe-Element am Ende:iframe // (The Dom Element) _views views manager rendition book reader
HINWEIS: Der Pfad ist in umgekehrter Reihenfolge
reader.book.rendition.manager.views._views.iframe
quelle
Ich möchte eine Änderung der Antwort von Zach / RegularMike vorschlagen (habe aber nicht den "Ruf", einen Kommentar abgeben zu können!). Ich fand diese Lösung eine sehr nützliche Basis, litt aber in meiner Anwendung, weil sie, wenn Zeichenfolgen in Arrays vorhanden sind, die Funktion für jedes Zeichen in der Zeichenfolge rekursiv aufruft (was dazu führte, dass IE11- und Edge-Browser mit Fehlern "Nicht genügend Stapelspeicher" fehlschlugen ). Meine einfache Optimierung bestand darin, den gleichen Test wie im rekursiven Aufruf der "Objekt" -Klausel zu dem in der "Array" -Klausel verwendeten hinzuzufügen:
if (arrayElem instanceof Object || arrayElem instanceof Array) {
Daher lautet mein vollständiger Code (der jetzt nach allen Instanzen eines bestimmten Schlüssels sucht, also etwas anders als die ursprüngliche Anforderung):
// Get all instances of specified property deep within supplied object function getPropsInObject(theObject, targetProp) { var result = []; if (theObject instanceof Array) { for (var i = 0; i < theObject.length; i++) { var arrayElem = theObject[i]; if (arrayElem instanceof Object || arrayElem instanceof Array) { result = result.concat(getPropsInObject(arrayElem, targetProp)); } } } else { for (var prop in theObject) { var objProp = theObject[prop]; if (prop == targetProp) { return theObject[prop]; } if (objProp instanceof Object || objProp instanceof Array) { result = result.concat(getPropsInObject(objProp, targetProp)); } } } return result; }
quelle
Vor einiger Zeit habe ich eine kleine Bibliothek erstellt
find-and
, die auf npm verfügbar ist , um mit verschachtelten Objekten auf lodash-Weise zu arbeiten. Da ist derreturnFound
Funktion, die das gefundene Objekt zurückgibt, oder ein Objektarray, wenn mehr als ein Objekt gefunden wurde.Z.B,
const findAnd = require('find-and'); const a = [ { 'title': "some title", 'channel_id':'123we', 'options': [ { 'channel_id':'abc', 'image':'http://asdasd.com/all-inclusive-block-img.jpg', 'title':'All-Inclusive', 'options':[ { 'channel_id':'dsa2', 'title':'Some Recommends', 'options':[ { 'image':'http://www.asdasd.com', 'title':'Sandals', 'id':'1', 'content':{}, }, ], }, ], }, ], }, ]; findAnd.returnFound(a, {id: '1'});
kehrt zurück
{ 'image':'http://www.asdasd.com', 'title':'Sandals', 'id':'1', 'content':{}, }
quelle
Verwenden Sie einfach die rekursive Funktion.
Siehe Beispiel unten:
const data = [ { title: 'some title', channel_id: '123we', options: [ { channel_id: 'abc', image: 'http://asdasd.com/all-inclusive-block-img.jpg', title: 'All-Inclusive', options: [ { channel_id: 'dsa2', title: 'Some Recommends', options: [ { image: 'http://www.asdasd.com', title: 'Sandals', id: '1', content: {}, } ] } ] } ] } ] function _find(collection, key, value) { for (const o of collection) { for (const [k, v] of Object.entries(o)) { if (k === key && v === value) { return o } if (Array.isArray(v)) { const _o = _find(v, key, value) if (_o) { return _o } } } } } console.log(_find(data, 'channel_id', 'dsa2'))
quelle
Eine andere rekursive Lösung, die für Arrays / Listen und Objekte oder eine Mischung aus beiden funktioniert:
function deepSearchByKey(object, originalKey, matches = []) { if(object != null) { if(Array.isArray(object)) { for(let arrayItem of object) { deepSearchByKey(arrayItem, originalKey, matches); } } else if(typeof object == 'object') { for(let key of Object.keys(object)) { if(key == originalKey) { matches.push(object); } else { deepSearchByKey(object[key], originalKey, matches); } } } } return matches; }
Verwendung:
let result = deepSearchByKey(arrayOrObject, 'key'); // returns an array with the objects containing the key
quelle
fucntion getPath(obj, path, index = 0) { const nestedKeys = path.split('.') const selectedKey = nestedKeys[index] if (index === nestedKeys.length - 1) { return obj[selectedKey] } if (!obj.hasOwnProperty(selectedKey)) { return {} } const nextObj = obj[selectedKey] return Utils.hasPath(nextObj, path, index + 1) }
Gern geschehen Von: Gorillaz
quelle
Mit diesem Code können Sie alle Objekte in einem JSON abrufen, dessen Schlüssel benutzerdefiniert ist.
function main(obj = {}, property){ const views = []; function traverse(o) { for (var i in o) { if(i === property) views.push(o[i]); if (!!o[i] && typeof(o[i])=="object") { console.log(i, o[i]); traverse(o[i]); } else { console.log(i, o[i]); } } } traverse(obj); return views; }
Hier ist ein Beispiel:
const obj = { id: 'id at level 1', level2: { id: 'id at level 2', level3: { id: 'id at level 3', level4: { level5: { id: 'id at level 5' } } } }, text: '' } main(obj, 'id');
quelle
Wenn Sie bereits Unterstrich verwenden, verwenden Sie _.find ()
_.find(yourList, function (item) { return item.id === 1; });
quelle