J'essaye de créer un objet arborescent imbriqué en utilisant un ensemble de données existant. L'ensemble de données d'origine est:
var obj = new Proxy({}, { get: function(target, name) { if (!(name in target)) { console.log("Non-existant property '" + name + "'"); var val = target[name] = typeof(target); //Returning reference to already created object return val; } } });
Je veux que mes données finales ressemblent à ceci:
"TypeError: Cannot set property 'B1' of undefined
Voici mes progrès jusqu'à présent.
var obj = {}; for(i = 0; i< raw_data.length; i++) { var [x,y,z,value] = raw_data[i]; obj[x][y][z] = value; }
Je boucle sur les données et j'exécute les valeurs de propriété de manière récursive sur une donnée vide.
Par exemple: Dans la 1ère itération, j'ai défini obj ['A1'] ['B1'] ['C1'] = 1
.
Cependant, cela pose problème car la première récursivité ( obj ['A1'
]) renverra undefined
donc l'erreur suivante:
{'A1': {'B1': {'C2': 2, 'C1': 1}, 'B2': {'C2': 6, 'C1': 4} }, 'A2': {'B1': {'C2': 10, 'C1': 8}, 'B2': {'C2': 14, 'C1': 12} } }
3 Réponses :
Vous pouvez utiliser une approche dynamique et réduire les clés données jusqu'au dernier élément et le prendre comme accesseur pour attribuer la valeur.
À l'intérieur de l'obtention du bon objet interne, un objet par défaut est assigné à une propriété, si le l'objet n'existe pas.
.as-console-wrapper { max-height: 100% !important; top: 0; }
function setValue(object, path, value) { var last = path.pop(); path.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value; return object; } var raw_data = [["A1", "B1", "C1", 1], ["A1", "B1", "C1", 2], ["A1", "B1", "C2", 3], ["A1", "B2", "C1", 4], ["A1", "B2", "C1", 5], ["A1", "B2", "C2", 6], ["A1", "B2", "C2", 7], ["A2", "B1", "C1", 8], ["A2", "B1", "C1", 9], ["A2", "B1", "C2", 10], ["A2", "B1", "C2", 11], ["A2", "B2", "C1", 12], ["A2", "B2", "C1", 13], ["A2", "B2", "C2", 14], ["A2", "B2", "C2", 15]], object = raw_data.reduce((r, a) => setValue(r, a.slice(0, -1), a[a.length - 1]), {}); console.log(object);
Avec ES6, vous pourriez faire
for(i = 0; i< raw_data.length; i++) { var [x,y,z,value] = raw_data[i]; obj[x] && obj[x][y] ? obj[x][y][z] = value : obj[x] ? obj[x][y] = {[z] : value} : obj[x] = {[y] : {[z] : value}}; }
Grâce à ComputedPropertyName (voir https://stackoverflow.com/a/2274327/3057341 )
Voici ma solution de code à votre problème. J'ai parcouru chaque élément du tableau de tableaux et peuplé l'objet en suivant la structure d'imbrication.
const raw_data = [ ["A1", "B1", "C1", 1], ["A1", "B1", "C2", 2], ["A1", "B2", "C1", 3], ["A1", "B2", "C1", 4], ["A1", "B2", "C2", 5], ["A1", "B2", "C2", 6], ["A2", "B1", "C1", 7], ["A2", "B1", "C1", 8], ["A2", "B1", "C2", 9], ["A2", "B1", "C2", 10], ["A2", "B2", "C1", 11], ["A2", "B2", "C1", 12], ["A2", "B2", "C2", 13], ["A2", "B2", "C2", 14] ]; let obj = {}; raw_data.forEach(element => { for(let i=0; i<4; i++){ let first_elem = element[0]; let second_elem = element[1]; let third_elem = element[2]; let fourth_elem = element[3]; switch(i){ case 0: if(!(first_elem in obj)){ obj[first_elem] = {}; } break; case 1: if(!(second_elem in obj[first_elem])){ obj[first_elem][second_elem] = {}; } break; case 2: if(!(third_elem in obj[first_elem][second_elem])){ obj[first_elem][second_elem][third_elem] = null; } break; case 3: if(fourth_elem != obj[first_elem][second_elem][third_elem]){ obj[first_elem][second_elem][third_elem] = fourth_elem; } break; } } }); console.log(obj);
Lorsque vous essayez d'accéder à la clé
A1
la première fois qu'elle n'existe pas. Vous devez donc le créer. La même chose se produit lorsque vous accédez à la toucheB1
de l'objetA1
.Ouais, je dois en quelque sorte renvoyer un objet proxy sur la référence créée précédemment, mais je ne sais pas vraiment comment faire cela.
Vous n'avez pas besoin d'un objet proxy. Vous pouvez certainement en utiliser un, mais ce serait un problème XY. En substance, vous devez vérifier si
obj [key]
existe et s'il ne l'instancie pas avant d'interagir avec luiobj [key] = {}
.Pourquoi toutes les valeurs finales
1
dans la sortie souhaitée.@MarkMeyer désolé que ce soit une faute de frappe. Édité.