2016-10-07 2 views
0

Я застрял на слиянии 2 объектов в один. Скажем, у меня есть 2 массивы объектов: Один Чайлдс:Присоединяйтесь к двум объектам по ключу

let childsWithMoreInfo = [{ 
    id: 1, 
    name: 'somename', 
    parent: { 
    id: 2 
    }, 
}, { 
    id: 2, 
    name: 'some child name', 
    parent: { 
    id: 4 
    } 
}]; 

И второй один Родители:

let parents = [{ 
    id: 1, 
    parentName: 'The first', 
    child: {} 
}, { 
    id: 2, 
    parentName: 'The second', 
    child: {} 
}, { 
    id: 3, 
    parentName: 'The third', 
    child: {} 
}, { 
    id: 4, 
    parentName: 'The fourth', 
    child: {} 
}]; 

И я бы объединить эти объекты, как это:

 let combined = [ 
      { 
       id: 1, 
       parentName: The first, 
       child: {} 
      }, 
      { 
       id: 2, 
       parentName: The second, 
       child: { 
        id: 1, 
        name: somename, 
       } 
      }, 
      { 
       id: 3, 
       parentName: The third, 
       child: {} 
      }, 
      { 
       id: 4, 
       parentName: The fourth, 
       child: { 
        id: 2 
        name: some child name, 
       } 
      }, 

     ] 
     ]; 

Итак, в основном это должно быть что-то вроде: let combinedList = parents.child = childsWithMoreInfo where parents.id = childsWithMoreInfo.parent.id. На каком методе я должен посмотреть? У вас есть идеи, как легко это достичь?

+1

Они слиты в ребенка. – crotoan

+0

Я рекомендую вам изучить lodash https: // lodash.ком/Docs/4.16.4. У них есть всевозможные функции, которые объединяют массивы в разных условиях. Разумеется, вы могли бы построить слияние с циклом в цикле. – Hampus

+0

@crotoan Перечитал вопрос. – guest271314

ответ

0

Вы можете использовать Map и итерации с Array#forEach для каждого объекта.

Затем выполните поиск на карте и присвойте значения родительскому объекту ch.

var childsWithMoreInfo = [{ id: 1, name: 'somename', parent: { id: 2 } }, { id: 2, name: 'some child name', parent: { id: 4 } }], 
 
    parents = [{ id: 1, parentName: 'The first', child: {} }, { id: 2, parentName: 'The second', child: {} }, { id: 3, parentName: 'The third', child: {} }, { id: 4, parentName: 'The fourth', child: {} }], 
 
    map = new Map; 
 

 
parents.forEach(p => map.set(p.id, p)); 
 
childsWithMoreInfo.forEach(c => { 
 
    var o = map.get(c.parent.id); 
 
    o.child = { id: c.id, name: c.name }; 
 
}); 
 
console.log(parents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Другим решением было бы использование Array#find

var childsWithMoreInfo = [{ id: 1, name: 'somename', parent: { id: 2 } }, { id: 2, name: 'some child name', parent: { id: 4 } }], 
 
    parents = [{ id: 1, parentName: 'The first', child: {} }, { id: 2, parentName: 'The second', child: {} }, { id: 3, parentName: 'The third', child: {} }, { id: 4, parentName: 'The fourth', child: {} }]; 
 

 
childsWithMoreInfo.forEach(c => { 
 
    var o = parents.find(p => p.id === c.parent.id); 
 
    o.child = { id: c.id, name: c.name }; 
 
}); 
 
console.log(parents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

Любые улучшения производительности с использованием карты по сравнению с итерацией на массиве JSON, использующей для/forEach? –

+0

карта имеет o (1), но вы можете использовать find –

+1

@AniketSinha это не «массив json», а только массив javascript. – zerkms

0

После кода имеет некоторые чистые функции, чтобы сделать вашу задачу. Я отформатировал/очищен исходные объекты также:

'use strict'; 
 

 
let childsWithMoreInfo = [{ 
 
    id: 1, 
 
    name: 'somename', 
 
    parent: { 
 
    id: 2 
 
    }, 
 
}, { 
 
    id: 2, 
 
    name: 'some child name', 
 
    parent: { 
 
    id: 4 
 
    } 
 
}]; 
 

 
let parents = [{ 
 
    id: 1, 
 
    parentName: 'The first', 
 
    child: {} 
 
}, { 
 
    id: 2, 
 
    parentName: 'The second', 
 
    child: {} 
 
}, { 
 
    id: 3, 
 
    parentName: 'The third', 
 
    child: {} 
 
}, { 
 
    id: 4, 
 
    parentName: 'The fourth', 
 
    child: {} 
 
}]; 
 

 
function makeObjectFromArray(arr) { 
 
    let obj = {}; 
 
    arr.map(function(item) { 
 
    if (obj[item.id] === undefined) { 
 
     obj[item.id] = item 
 
    } 
 
    }) 
 
    return obj; 
 
} 
 

 
function toArray(obj) { 
 
    return Object.keys(obj).map(function(key) { 
 
    return obj[key] 
 
    }); 
 
} 
 

 
function sampleParentChildren(parent, children) { 
 
    let Parent = {}; 
 
    if (parent.constructor === Array) { 
 
    Parent = makeObjectFromArray(parent); 
 
    } else { 
 
    Parent = Object.assign({}, parent) 
 
    } 
 
    children.map(function(child) { 
 
    if (Parent[child.parent.id] !== undefined) { 
 
     if (Parent[child.parent.id].child === undefined) { 
 
     Parent[child.parent.id].child = {}; 
 
     } 
 
     Parent[child.parent.id].child[child.id] = child 
 
    } 
 

 
    }); 
 
    return Parent; 
 
} 
 
let resampledData = sampleParentChildren(parents, childsWithMoreInfo); 
 
console.log(resampledData, toArray(resampledData));

0

Чтобы присоединиться к массивам в ES6, вы можете использовать оператор распространения присоединиться массивами и просто использовать обычный старый forEach к deduping. Оператор распространения более декларативный, чем методы массива конкатенации ES5 как упоминалось here на MDN

[...parents, ...childsWithMoreInfo] 

Вот рабочий пример:

let childsWithMoreInfo = [{ 
 
    id: 1, 
 
    name: 'somename', 
 
    parent: { 
 
     id: 2 
 
    }, 
 
    }, { 
 
    id: 2, 
 
    name: 'some child name', 
 
    parent: { 
 
     id: 4 
 
    } 
 
    }], 
 
    parents = [{ 
 
     id: 1, 
 
     parentName: 'The first', 
 
     child: {} 
 
    }, { 
 
     id: 2, 
 
     parentName: 'The second', 
 
     child: {} 
 
    }, { 
 
     id: 3, 
 
     parentName: 'The third', 
 
     child: {} 
 
    }, { 
 
     id: 4, 
 
     parentName: 'The fourth', 
 
     child: {} 
 
    }, 
 

 
    ]; 
 

 
var conjoined = [...parents, ...childsWithMoreInfo]; 
 

 
conjoined.forEach(function(parentConjoinee, parentIndex) { 
 
    conjoined.forEach(function(childConjoinee, childIndex) { 
 
    if (parentConjoinee.id === childConjoinee.id && parentIndex !== childIndex) { 
 
     conjoined.splice(childIndex, 1); 
 
    } 
 
    }); 
 
}); 
 

 
console.log(conjoined);

0

Вы можете использовать вложенные for петли, break

var childsWithMoreInfo = [{ 
 
    id: 1, 
 
    name: "somename", 
 
    parent: { 
 
    id: 2 
 
    } 
 
}, { 
 
    id: 2, 
 
    name: "some child name", 
 
    parent: { 
 
    id: 4 
 
    } 
 
}]; 
 

 
var parents = [{ 
 
    id: 1, 
 
    parentName: "The first", 
 
    child: {} 
 
    }, { 
 
    id: 2, 
 
    parentName: "The second", 
 
    child: {} 
 
    }, { 
 
    id: 3, 
 
    parentName: "The third", 
 
    child: {} 
 
    }, { 
 
    id: 4, 
 
    parentName: "The fourth", 
 
    child: {} 
 
    } 
 

 
]; 
 
let combined = []; 
 
for (var i = 0; i < parents.length; i++) { 
 
    for (var j = 0; j < childsWithMoreInfo.length; j++) { 
 
    if (childsWithMoreInfo[j].parent.id === parents[i].id) { 
 
     parents[i].child.id = childsWithMoreInfo[j].id; 
 
     parents[i].child.name = childsWithMoreInfo[j].name; 
 
     break; 
 
    } 
 
    } 
 
    combined.push(parents[i]) 
 
}; 
 

 
console.log(combined);

+0

Я бы пошел с тем же подходом, поскольку это проще, если только кто-то не докажет улучшения производительности, используя карту. –

1

Я действительно знаю, как использовать Foreach, я хотел бы избежать.

Это то, что я сделал:

this.combined = _.map(parents, (parent) => { 
      parent.child = childs.find(child => child.parent.id === parent.id); 
     return parent; 
    }); 

Спасибо за все ваши ответы.

+1

Почему бы не встроить JS массив 'map'? – zerkms

+0

https://lodash.com/docs/4.16.4#map, – crotoan

+0

Есть ли причина предпочесть его над' Array.prototype.map'? – zerkms

Смежные вопросы