2017-08-05 3 views
0

Je travaille avec un ensemble de données qui ne peut pas être modifié côté serveur. J'essaie donc de configurer le modèle de données local sur le client d'une manière que je puisse facilement traverser le modèle lors de la mise à jour de certaines parties des données. Par conséquent, j'essaie de créer une carte à plusieurs niveaux à partir de cartes à plusieurs niveaux, y compris des listes, qui incluent elles-mêmes des cartes, etc. (voir les schémas à la fin de cet article). Ce que j'essaye d'obtenir est une carte contenant d'autres cartes, avec la clé de la carte incluse étant la valeur de l'objet (encore s'il vous plaît voir les schémas à la fin de ce post).Créer des cartes à partir de listes imbriquées avec Immutable.js

J'ai eu à travailler sur le premier niveau:

const firstLevel = data.toMap().mapKeys((key, value) => value.get('value')); 

voir en action ici: https://jsfiddle.net/9f0djcb0/4/

Mais il y a un maximum de 3 niveaux de données imbriquées et je ne peux pas obtenir mon la tête autour de la façon de faire la transformation. Toute aide appréciée!

Les jeux de données schématiques:

// This is what I got 
const dataset = [ 
    { 
    field: 'lorem', 
    value: 'ipsum', 
    more: [ 
     { 
     field: 'lorem_lvl1', 
     value: 'ispum_lvl1', 
     more: [ 
      { 
      field: 'lorem_lvl2', 
      value: 'ispum_lvl2', 
      more: [ 
       { 
       field: 'lorem_lvl3', 
       value: 'ispum_lvl3', 
       } 
      ] 
      } 
     ] 
     } 
    ] 
    }, 
    { 
    field: 'glorem', 
    value: 'blipsum' 
    }, 
    { 
    field: 'halorem', 
    value: 'halipsum' 
    } 
]; 

C'est là où je veux aller:

// This is what I want 
const dataset_wanted = { 
    ipsum: { 
    field: 'lorem', 
    value: 'ipsum', 
    more: { 
     lorem_lvl1: { 
     field: 'lorem_lvl1', 
     value: 'ispum_lvl1', 
     more: { 
      lorem_lvl2: { 
      field: 'lorem_lvl2', 
      value: 'ispum_lvl2', 
      more: { 
       lorem_lvl3: { 
       field: 'lorem_lvl3', 
       value: 'ispum_lvl3', 
       } 
      } 
      } 
     } 
     } 
    } 
    }, 
    glorem: { 
    field: 'glorem', 
    value: 'blipsum' 
    }, 
    halorem: { 
    field: 'halorem', 
    value: 'halipsum' 
    } 
}; 

Répondre

0

En ce qui concerne une solution plus générative, je re-écrit la réponse avant une approche récursive:

function mapDeep(firstLevel) { 
    return firstLevel.map((obj) => { 
    if (obj.has('more')) { 
     const sec = obj.get('more').toMap().mapKeys((key, value) => value.get('value')); 
     const objNext = mapDeep(sec); 
     obj = obj.set('more', objNext); 
    } 
    return obj; 
    }); 
} 

Le premier niveau doit encore être mis en correspondance manuellement avant.

const firstLevel = data.toMap().mapKeys((key, value) => value.get('value')); 
const secondLevel = mapDeep(firstLevel); 

Encore une fois, le voir en action: https://jsfiddle.net/9f0djcb0/12/

Ceci est assez bon pour moi pour l'instant. On se sent encore comme cela peut être résolu plus intelligent (et plus performant) .. Cheers :)

0

Récupérer des structures imbriquées en utilisant "Getin" est Beter.

const data = Immutable.fromJS(dataset[0]); 
const firstLevel = data.getIn(['more']); 
const twoLevel = firstLevel.getIn([0,'more']); 
const threeLevel = twoLevel.getIn([0,'more']); 
console.log(firstLevel.toJS(),twoLevel.toJS(),threeLevel.toJS()); 
+0

Salut @Coder, merci pour votre réponse rapide. J'ai l'idée de récupérer des données imbriquées à la demande. Mais ce que j'essaie de réaliser, ce n'est pas simplement de "lire" la structure imbriquée, mais de la * convertir * de l'exemple A (// C'est ce que j'ai) à l'exemple B (// C'est ce que je veux). Je ne comprends pas comment je peux y arriver avec l'aide de getIn(). Pouvez-vous s'il vous plaît expliquer un peu plus en profondeur? – derdaani

0

Donc, après un certain temps passé, je suis venu avec une solution qui fonctionne pour moi:

let sec, third, objThird; 

// 1st level: simple mapping 
const firstLevel = data.toMap().mapKeys((key, value) => value.get('value')); 

// 2nd level: walk through updated firstLevel's subobjects and do the mapping again: 
const secondLevel = firstLevel.map((obj) => { 
    if (obj.has('more')) { 
    sec = obj.get('more').toMap().mapKeys((key, value) => value.get('value')); 

    // 3nd level: walk through updated secondLevel's subobjects and do the mapping again: 
    objThird = sec.map((o) => { 
     if (o.has('more')) { 
     third = o.get('more').toMap().mapKeys((key, value) => value.get('value')); 
     o = o.set('more', third); 
     } 
     return o; 
    }); 
    obj = obj.set('more', objThird); 
    } 
    return obj; 
}); 

voir en action ici: https://jsfiddle.net/9f0djcb0/7/

Cela a travaillé bien jusqu'à présent, JEU. assez codé en dur. Si quelqu'un a une solution plus élégante à cela, je suis heureux d'apprendre à ce sujet!