简体   繁体   中英

select data from two different arrays of objects to create a new array of objects

I have the following arrays of objects:

const formulas =
[
    { "formulaID": "1", "versionID": 1, "formulaClass": 3, "formulaType": "34", "outputName": "Chocolate Milk 2%" },
    { "formulaID": "4", "versionID": 1, "formulaClass": 3, "formulaType": "17", "outputName": "Hazelnut Creamer" },
    { "formulaID": "6", "versionID": 1, "formulaClass": 3, "formulaType": "23", "outputName": "White Milk 2%" }
];

const yields =
[
    { "formulaID": "4", "versionID": 1, "yieldFactor": 0.93 },
    { "formulaID": "4", "versionID": 2, "yieldFactor": 0.98 },
    { "formulaID": "6", "versionID": 1, "yieldFactor": 0.95 },
    { "formulaID": "7", "versionID": 1, "yieldFactor": 0.85 }
];

and am trying to programmatically create this output:

const result =
[
    { "formulaID": "7", "versionID": 1, "yieldFactor": 0.85, "outputName": "" },
    { "formulaID": "4", "versionID": 1, "yieldFactor": 0.93, "outputName": "Hazelnut Creamer" },
    { "formulaID": "4", "versionID": 2, "yieldFactor": 0.98, "outputName": "" },
    { "formulaID": "6", "versionID": 1, "yieldFactor": 0.95, "outputName": "White Milk 2%" }
];

With the help of this post I wrote this code:

const result = yields.map(yld => ({
    formulaID: yld.formulaID,
    versionID: yld.versionID,
    yieldFactor: yld.yieldFactor,
    outputName: formulas.filter(f => (f.formulaID + '-' + f.versionID).includes(yld.formulaID + '-' + yld.versionID))
}));

console.log(result);

It is close to the desired outcome but I'm not sure how to isolate just the outputName . In its current state it's giving the entire array where a match is found. How do I display only the outputName for matches and an empty string for outputName where there is no match between the original arrays of source data?

Edit - The current output looks like this: 在此处输入图像描述

Using .filter will always return an array of formulas satisfying your condition, so you need to check if it gave results first, then retrieve only .outputName from its results.

Could be something like this:

const result = yields.map(yld => {
  const targetFormulas = formulas.filter(f => (f.formulaID + '-' + f.versionID).includes(yld.formulaID + '-' + yld.versionID));
  const outputName = targetFormulas.length ? targetFormulas.map(f => f.outputName).join(',') : ''
  return {
    formulaID: yld.formulaID,
    versionID: yld.versionID,
    yieldFactor: yld.yieldFactor,
    outputName
  }
});

I've used a .join(',') to return outputNames separated by comma, if there are more than 1.
If you're sure that only 1 will be returned, you can do targetFormulas.map(f => f.outputName)[0]

This will return the following result

[
   {
      "formulaID":"4",
      "versionID":1,
      "yieldFactor":0.93,
      "outputName":"Hazelnut Creamer"
   },
   {
      "formulaID":"4",
      "versionID":2,
      "yieldFactor":0.98,
      "outputName":""
   },
   {
      "formulaID":"6",
      "versionID":1,
      "yieldFactor":0.95,
      "outputName":"White Milk 2%"
   },
   {
      "formulaID":"7",
      "versionID":1,
      "yieldFactor":0.85,
      "outputName":""
   }
]

Try to use reduce method with Map collection to have O(1) while mapping elements:

const uniqueUtems = new Map(formulas.map(s=>[s.formulaID, s.outputName]));

const result = yields.reduce((a, {formulaID, ...rest}) => {
    a.push({ formulaID , outputName: uniqueUtems.get(formulaID) || '', ...rest });
    if (uniqueUtems.has(formulaID))
        uniqueUtems.delete(formulaID)
    return a;
}, []);

console.log(result);

An example:

 const formulas = [ { "formulaID": "1", "versionID": 1, "formulaClass": 3, "formulaType": "34", "outputName": "Chocolate Milk 2%" }, { "formulaID": "4", "versionID": 1, "formulaClass": 3, "formulaType": "17", "outputName": "Hazelnut Creamer" }, { "formulaID": "6", "versionID": 1, "formulaClass": 3, "formulaType": "23", "outputName": "White Milk 2%" } ]; const yields = [ { "formulaID": "4", "versionID": 1, "yieldFactor": 0.93 }, { "formulaID": "4", "versionID": 2, "yieldFactor": 0.98 }, { "formulaID": "6", "versionID": 1, "yieldFactor": 0.95 }, { "formulaID": "7", "versionID": 1, "yieldFactor": 0.85 } ]; const uniqueUtems = new Map(formulas.map(s=>[s.formulaID, s.outputName])); const result = yields.reduce((a, {formulaID, ...rest}) => { a.push({ formulaID, outputName: uniqueUtems.get(formulaID) || '', ...rest }); if (uniqueUtems.has(formulaID)) uniqueUtems.delete(formulaID) return a; }, []); console.log(result);

...rest is:

The rest parameter syntax allows us to represent an indefinite number of arguments as an array.

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