2017-10-20 11 views
0

J'essaie de combiner les objets imbriqués à l'intérieur d'éléments avec la même clé.Combiner des tableaux d'objets correspondants

  • Find « haut niveau » valeurs qui sont dupliquées,
  • combinons les éléments de « haut niveau » en double en un seul objet (y compris leurs enfants.
  • Il devrait y avoir aucune valeur en double à l'intérieur des réseaux « de type »

Je l'ai essayé ici https://jsfiddle.net/Lpq6huvw/410/

données d'entrée:

[{ 
    "a": "Mon", 
    "type": [{ 
     "b": 1 
    }, { 
     "b": 3 
    }] 
}, { 
    "a": "Mon", 
    "type": [{ 
     "b": 2 
    }] 
}, { 
    "a": "Tue", 
    "type": [{ 
     "b": 40 
    }] 
}, { 
    "a": "Tue", 
    "type": [{ 
     "b": 50 
    }] 
}, { 
    "a": "Wed", 
    "type": [{ 
     "b": 30 
    }] 
}] 

Dans ce tableau:

[{ 
     "a": "Mon", 
     "type": [{ 
     "b": 1 
     }, { 
     "b": 3 
     }, 
     { 
     "b": 2 
     }] 
    }, 
    { 
     "a": "Tue", 
     "type": [{ 
     "b": 40 
     }, 
     { 
     "b": 50 
     }] 
    }, { 
     "a": "Wed", 
     "type": [{ 
     "b": 30 
     }] 
    }] 

J'ai essayé ce ci-dessous, qui mappe tous les éléments dupliqués comme un seul objet. Cependant, je veux qu'il cartographie chaque sous son prédécesseur de «niveau supérieur».

const z = _.uniqBy(_.filter(data.map(e=>e.a), v => _.filter(data.map(e=>e.a), v1 => v1 === v).length > 1)) 
const dupes = data.filter(itm => z.includes(itm.a)) 

const flat = _.flatMap(dupes, item => 
         _(item.type) 
          .map(v => ({b: v.b})) 
          .value() 
) 
+0

Est-ce que les noms de propriétés toujours le même, avec des valeurs changeant juste? – nnnnnn

+0

Oui, ils resteront les mêmes – Ycon

+1

* "Il ne devrait pas y avoir de valeurs dupliquées dans les tableaux 'type'" * - Voulez-vous dire que l'entrée n'aura jamais de valeurs 'type' dupliquées, ou que l'entrée pourrait avoir des doublons mais la sortie ne devrait pas? – nnnnnn

Répondre

2

Je trouve personnellement un travail Javascript est construit dans les fonctions agréable, et semble plus facile à suivre que certaines des fonctions de lodash.

par ex.

var data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2},{"b":3}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 
    
 
var result = data.reduce((acc, val) => { 
 
    var found = acc.find((findval) => val.a === findval.a); 
 
    if (!found) acc.push(val) 
 
    else found.type = found.type.concat(
 
    val.type.filter((f) => !found.type.find((findval) => f.b === findval.b))); 
 
    return acc; 
 
}, []); 
 
    
 
console.log(result);

+0

Grande implémentation minimale. Juste un peu confus quant à la raison pour laquelle les données ont été nommées 'var a' alors il retourne' a'. De toute façon, ça marche! – Ycon

+0

'a' dans le retour est l'accumulateur en fonction de réduction. Je vais renommer certaines des vars pour éviter la confusion. – Keith

+0

FYI Je le combine avec cette solution d'une autre question- https://stackoverflow.com/questions/46845461 – Ycon

1

est ici une réponse w/o lodash:

function combine (input) { 
    const hash = input.reduce((result, current) => { 
    if (result[current['a']]) { 
     result[current['a']] = result[current['a']].concat(current['type']) 
    } else { 
     result[current['a']] = current['type'] 
    } 

    return result 
    }, {}) 

    return Object.keys(hash).map(key => { 
    return { 
     a: key, 
     type: hash[key] 
    } 
    }) 
} 
1

ES6: vous pouvez itérer aveC# Array réduisent, recueillir les éléments dans une carte, puis reconvertir en un tableau avec la syntaxe diffusion et associez des valeurs #:

const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 
const result = [...data.reduce((m, { a, type }) => { 
 
    const item = m.get(a) || { a, type: [] }; // use a Set to maintain uniqueness 
 
    
 
    item.type.push(...type); 
 
    
 
    return m.set(a, item); 
 
}, new Map).values()] 
 
.map(({ a, type }) => ({ // make types unique again 
 
    a, 
 
    type: [...type.reduce((m, o) => m.has(o.b) ? m : m.set(o.b, o), new Map).values()] 
 
})); 
 

 

 
console.log(result);

Lodash: Utilisez _.groupBy() pour obtenir tous les objets ayant la même propriété a dans un groupe. Mappez les groupes et fusionnez chaque groupe en utilisant _.mergeWith() et concattez tous les tableaux type. Effectuez un autre passage avec map pour que tous les éléments des tableaux type soient uniques.

const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}]; 
 

 

 
const result = _(data) 
 
    .groupBy('a') 
 
    .map((group) => _.mergeWith({}, ...group, ((objValue, srcValue, key) => 
 
    key === 'type' ? (objValue || []).concat(srcValue) : undefined 
 
))) 
 
    .map((obj) => Object.assign(obj, { type: _.uniq(obj.type) })) 
 
    .value(); 
 

 
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

Thansk pour ceux-ci - mais aucun ne semble montrer plusieurs éléments à l'intérieur de la propriété 'b'. Pourriez-vous chceck? – Ycon

+0

Le lodash est unique. J'ai corrigé l'ES6. –