简体   繁体   中英

Add object contents in one object array within objects in another array

I have two large files containing object arrays, the first containing data like this:

[{
    "id": "001",
    "word": "abbess",
    "def": "(noun) The lady superior of a nunnery",
}, {
    "id": "002"
    "word": "abbey",
    "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.",
}, (etc...)

The second, data like this:

[{
    "meta": {
        "term": "abbess",
        "part_of_speech": "noun",
        "definition": "The lady superior of a nunnery"
    }
}, {
    "meta": {
        "term": "abbey",
        "part_of_speech": "noun",
        "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns"
    }
}, (etc...)

I want to combine these two files so the "meta" information from the second file is added to the corresponding information from the first file, so:

[{
    "id": "001",
    "word": "abbess",
    "def": "(noun) The lady superior of a nunnery",
    "meta": {
        "term": "abbess",
        "part_of_speech": "noun",
        "definition": "The lady superior of a nunnery"
    }
}, {
    "id": "002"
    "word": "abbey - (noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.",
    "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.",
    "meta": {
        "term": "abbey",
        "part_of_speech": "noun",
        "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns"
    }
}, (etc...)

Right now, I'm have this code

 var newArr = [];
 for(var i = 0; i < meta.length; i++) {
    newArr.push(words[i]);
    newArr.push(meta[i]);
 }

that adds the meta objects after the words object, not within. Do I need to loop down another layer to add the meta objects within the words objects, or is there a different method that would work better here, like .concat()?

If each element in each array corresponds to the other element with the same index in the other array, then it's a simple .map , which is more appropriate than a for loop:

 const input1 = [{ "id": "001", "word": "abbess", "def": "(noun) The lady superior of a nunnery", }, { "id": "002", "word": "abbey", "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.", }]; const input2 = [{ "meta": { "term": "abbess", "part_of_speech": "noun", "definition": "The lady superior of a nunnery" } }, { "meta": { "term": "abbey", "part_of_speech": "noun", "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns" } }]; const combined = input1.map((item) => { const { word } = item ; const foundInput2 = input2.find(({ meta: { term }}) => term === word); const { meta } = foundInput2; return { ...item, meta }; }); console.log(combined); 

loop through the array of metas and use Object.assign to add the meta to the corresponding object in the first array :

 var arr = [{ "id": "001", "word": "abbess", "def": "(noun) The lady superior of a nunnery", }, { "id": "002", "word": "abbey", "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.", }] const arr2 = [{ "meta": { "term": "abbess", "part_of_speech": "noun", "definition": "The lady superior of a nunnery" } }, { "meta": { "term": "abbey", "part_of_speech": "noun", "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns" } }] arr2.forEach((e, i) => { Object.assign(arr[i], e); }); console.log(arr) 

In case the arrays doesn't line up, you can use .map and .find to achieve your goal.

 const input1 = [{ "id": "001", "word": "abbess", "def": "(noun) The lady superior of a nunnery", }, { "id": "002", "word": "abbey", "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.", }]; const input2 = [{ "meta": { "term": "abbess", "part_of_speech": "noun", "definition": "The lady superior of a nunnery" } }, { "meta": { "term": "abbey", "part_of_speech": "noun", "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns" } }]; const output = input1.map(item => { return { ...item, ...input2.find(item2 => item2.meta.term === item.word) } }); console.log(output); 

Just set the new property of the object from the first array.

 var newArr = [];
 for(var i = 0; i < meta.length; i++) {
    var word = words[i];
    word.meta = meta[i].meta;
    newArr.push(word);
 }

This is assuming that both arrays will always have info of the same word in the same order.

Bonus tip - if you are using ECMAScript 6, you could concatenate the objects like this:

 const newArr = [];
 for(let i = 0; i < meta.length; i++) {
    newArr.push({ ...words[i], ...meta[i]} );
 }

An alternative is using the function reduce + function map

The function reduce converts the second array input2 to an object where keys are coming from the attribute meta.term , this way the function map uses that object to find very fast the corresponding meta values by key rather than a repeated find execution.

This approach works independently of the order because will match the attributes word and attributes meta.term .

 const input1 = [{ "id": "001", "word": "abbess", "def": "(noun) The lady superior of a nunnery",}, { "id": "002", "word": "abbey", "def": "(noun) The group of buildings which collectively form the dwelling-place of a society of monks or nuns.",}], input2 = [{ "meta": { "term": "abbess", "part_of_speech": "noun", "definition": "The lady superior of a nunnery" }}, { "meta": { "term": "abbey", "part_of_speech": "noun", "definition": "The group of buildings which collectively form the dwelling-place of a society of monks or nuns" }}], mapped = input2.reduce((a, o) => Object.assign(a, {[o.meta.term]: o.meta}), {}), result = input1.map((o) => Object.assign({}, o, {meta: mapped[o.word]})); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM