【问题标题】:select data from two different arrays of objects to create a new array of objects从两个不同的对象数组中选择数据以创建一个新的对象数组
【发布时间】:2020-04-29 14:54:38
【问题描述】:

我有以下对象数组:

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 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%" }
];

this post的帮助下,我写了这段代码:

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);

它接近预期的结果,但我不确定如何仅隔离 outputName。在其当前状态下,它给出了找到匹配项的整个数组。在原始数据数组之间不匹配的情况下,如何仅显示 outputName 匹配和空字符串 outputName

编辑 - 当前输出如下所示:

【问题讨论】:

  • 你当前的输出是多少?
  • 试试:yields.map(yld => ({...yld, outputName: (formulas.find(f => f.formulaID === yld.formulaID && f.versionID === yld.versionID) || {}).outputName});
  • @Titus - 你会考虑发布这条评论作为答案吗?

标签: javascript arrays object


【解决方案1】:

使用.filter 将始终返回满足您条件的公式数组,因此您需要先检查它是否给出了结果,然后仅从其结果中检索.outputName

可能是这样的:

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
  }
});

如果有超过 1 个,我使用 .join(',') 返回以逗号分隔的 outputNames。
如果你确定只有 1 会被退回,你可以这样做 targetFormulas.map(f => f.outputName)[0]

这将返回以下结果

[
   {
      "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":""
   }
]

【讨论】:

    【解决方案2】:

    尝试将reduce 方法与Map 集合一起使用,以便在映射元素时拥有O(1)

    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);
    

    一个例子:

    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:

    rest 参数语法允许我们表示一个不定数 参数作为一个数组。

    【讨论】:

    • 什么是...rest
    • 另外,此解决方案是否考虑了构成每个对象的键的 2 个属性 formulaIDversionID
    • 这没有给出正确的结果 formulaID = 4 有 2 个不同的 versionIDs。它正在为此formulaID 的两个版本ID 填充outputName,但它应该只为versionID = 1 填充它。
    • @knot22 哎呀,我已经编辑了我的回复。请看我更新的回复。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2021-03-30
    • 2021-07-03
    相关资源
    最近更新 更多