2017-08-01 1 views
1

Ich habe derzeit mit einem JavaScript-Problem zu kämpfen. Ich möchte eine mehrstufige Eigenschaft sowie alle darin enthaltenen Variablen zurückgeben, indem ich das ursprüngliche Objekt und ein Array von Pfaden an die gewünschten Eigenschaften übergebe.Zugriff auf Multi-Level-Eigenschaft und den vollständigen Pfad der Eigenschaften

Zum Beispiel, wenn ich folgendes Objekt:

obj = { 
    product: { 
    candidate: { 
     id: 10, 
     reference: "test", 
     count: 4, 
     steps: 10 
    } 
    } 
} 

Ich möchte eine Methode aufrufen können:

getVarPath(obj, ["product.candidate.ID", "product.candidate.reference"]) 

Und es dann mit jeder Variablen ein Objekt zurückgeben bestanden haben, in das Array, in seiner ursprünglichen Struktur. So wäre dies ein Objekt zurückgeben, wie so sucht:

{ 
    product: { 
    candidate: { 
     id: 10, 
     reference: "test" 
    } 
    } 
} 

habe ich diese Arbeit in meiner lokalen Lösung im Moment (in einem String übergeben, anstatt ein Array im Moment).

Die Lösung im Moment ist ziemlich schrecklich, aber ich freue mich darauf, es zu verbessern, wenn also jemand eine bessere Methode vorstellen könnte, die großartig wäre. Noch einmal, das ist jetzt ziemlich schrecklich, aber ich möchte es verbessern. Aber es macht den Job:

var getVarPath = function(obj, keys){ 
    var elements = keys.split("."), 
     evalStr = "", 
     objStr = "obj", 
     newObjStr = "newObj", 
     newObj = {}; 

    if(elements.length > 1){ 

    elements.forEach(function(key, index){ 

     // first append a property accessor at the end of the eval string 
     evalStr = evalStr + "['" + key + "']"; 

     // if we're at the last element, we've reached the value, so assign it 
     if(index === elements.length -1){ 

     eval(newObjStr + evalStr + " = " + objStr + evalStr); 
     } 
     else { 
     // if we're not at the last, we're at an object level 
     // if the nested object doesn't exist yet, create it 
     if(!eval(newObjStr + evalStr)){ 
      eval(newObjStr + evalStr + " = {};"); 
     } 
     } 
    }); 

    } 

    return newObj; 
} 
+1

Was Sie versucht haben, bisher? –

+0

Ich habe die Frage mit meiner aktuellen Arbeitslösung bearbeitet, aber ich mag die Tatsache nicht, dass ich Eval benutze, um es ein bisschen schöner zu machen – TomDavies

Antwort

0

Für jedes Element in dem Eingangsfeld:

Erstens können Sie die ursprüngliche Zeichenfolge aufgeteilt: var nestedElements="product.candidate.ID".split(.)"
Dies gibt einen Array mit jedem Level: ["product","candidate","ID"]

Jetzt können Sie mit jedem Element des Arrays auf Ihr geschachteltes Objekt zugreifen: obj["product"]["candidate"]["ID"] entweder mit einer Schleife über das Array oder die Rekursion.

var currentobj=obj; 
for (var i=0;i<nestedElements.length;i++){ 
    currentobj=currentobj[nestedElements[i]] 
} 
// currentobj is your id  

Im gleichen Prozess, könnten Sie dynamisch Elemente zu einem neuen hinzufügen obj ein ähnliches Verfahren:

newobj={} //before loop 
if (newobj["product"] === undefined) newobj["product"]={} //in loop 

Und das sollte für jedes Element auf dem Eingangsfeld erfolgen, in dem Ende Iteration durch Arrays und Zugriff auf das Objekt mit Zeichenfolgen

+0

Hey, danke für deine Antwort! Ich habe versucht, Ihr Beispiel hier zu implementieren, aber es scheint nicht zu funktionieren, ich bekomme Ausnahmen, wenn es versucht, tiefer als ein Element zu gehen, hast du das selbst funktioniert? – TomDavies

+0

Dieses Beispiel ist meist Pseudocode mit der grundlegenden Logik, nicht wirklich funktionierenden Code, Sie müssen es anpassen. Welche Ausnahmen erhalten Sie? – angrykoala

0

Ihr Code, wie er ist, sollte eigentlich nicht funktionieren. Sie behandeln keys als eine Zeichenfolge, aber übergeben in einem Array. Sie können (und sollten) die Verwendung von eval() vermeiden, indem Sie die "inneren" Objekte, die Sie gerade betrachten, im Auge behalten und object[property] anstelle von object.property verwenden.

function getVarPath(obj, keys) { 
 
    var result = {}; 
 

 
    // ["product.candidate.id", "product.candidate.reference"] 
 
    keys.forEach(function(key) { 
 
    var src = obj,  // inner source object 
 
     dest = result, // inner destination object 
 
     parts = key.split(/\./); 
 

 
    // e.g. ["product", "candidate", "id"] 
 
    parts.forEach(function(part) { 
 

 
     // if we're looking at an object, make sure it exists in the dest 
 
     if (typeof(src[part]) === "object") 
 
     dest[part] = dest[part] || {}; 
 
     // if it's just a value, copy it 
 
     else 
 
     dest[part] = src[part]; 
 

 
     dest = dest[part]; // move from obj to obj.product, then to obj.product.candidate, etc. 
 
     src = src[part]; 
 
    }); 
 
    }); 
 

 
    return result; 
 
} 
 

 
var obj = { 
 
    product: { 
 
    candidate: { 
 
     id: 10, 
 
     reference: "test", 
 
     count: 4, 
 
     steps: 10 
 
    } 
 
    } 
 
} 
 

 
var output = getVarPath(obj, ["product.candidate.id", "product.candidate.reference"]); 
 

 
console.log(JSON.stringify(output));

0

Mit _.propertyOf(), Array#reduce() und Object.assign() sowie computed property names, könnten Sie eine weniger schwierige Implementierung an:

function getVarPath(object, paths) { 
 
    return paths.reduce(function (accumulator, path) { 
 
    const that = _.propertyOf(accumulator) 
 
    let walk = path.split('.') 
 
    let value = this(walk) 
 

 
    for (let key = walk.pop(); key !== undefined; key = walk.pop()) { 
 
     const base = that(walk) 
 

 
     value = { [key]: value } 
 

 
     if (base !== undefined) { 
 
     value = Object.assign(base, value) 
 
     } 
 
    } 
 

 
    return Object.assign(accumulator, value) 
 
    }.bind(_.propertyOf(object)), {}) 
 
} 
 

 
let obj = { 
 
    product: { 
 
    candidate: { 
 
     id: 10, 
 
     reference: "test", 
 
     count: 4, 
 
     steps: 10 
 
    } 
 
    } 
 
} 
 

 
console.log(getVarPath(obj, ['product.candidate.id', 'product.candidate.reference']))
<script src="https://cdn.rawgit.com/lodash/lodash/4.17.4/dist/lodash.min.js"></script>

Verwandte Themen