【问题标题】:Merge objects using lodash使用 lodash 合并对象
【发布时间】:2018-08-07 11:16:21
【问题描述】:

如何将以下对象合并为一个:

对象一

{"risks": [
    {
        "forests_wildlife": ["The landscape"],
        "other": ["Something here"]
    } 
]}

对象二

{"riskDetails": [
    {
        "forests_wildlife": "The landscape",
        "affected_people": "1000-10,000",
        "affected_wildlife": "2-5 wildlife populations"
    },
    {
        "other": "Custom",
        "affected_people": "100-1000",
        "affected_wildlife": "5-10 wildlife populations"
    } 
]}

期望的输出

{"risks": [
    {
        "forests_wildlife": [
            {
                "The landscape" : {
                    "riskDetails": {
                        "affected_people": "1000-10,000",
                        "affected_wildlife": "2-5 wildlife populations"
                    }
                }
            }
        ],
        "other": [
            {
                "Custom something" : {
                    "riskDetails": {
                        "affected_people": "100-1000",
                        "affected_wildlife": "5-10 wildlife populations"
                    }
                }
            }
        ]
    },...
]}

我非常感谢任何帮助。只要解决方案有效,Lodash 或没有 lodash 就可以了。

编辑:

我认为,出于我的目的,我实际上不必将两者组合成一个对象,而可以只检查第一个中的每个项目并在第二个中找到匹配项。这是我想出的对我有用的 sn-p:

        const riskCategory = data.risks;
        const riskDetails = data.riskDetails;
        return _.map(riskCategory, category => {
            return _.map(category, (risk, key) => {
                return _.map(risk, (item, index) => {
                    var details = _.find(riskDetails, _.matchesProperty( key, item ));
                    if ( details ) {
                        return (
                            <tr key={index}>
                                <td> {item} </td>
                                <td> {details.affected_people} </td>
                                <td> {details.affected_wildlife} </td>
                            </tr>
                        );
                    }
                    return;
                });
            });
        });

这是一个嵌套地图,在中间的某处查找和匹配,以便能够到达第二个对象的最里面。也许还有另一种更清洁、更优雅的方法。我是 javascript 新手,我发现 lodash 帮助我让我的生活更轻松一些,但我不想过分依赖它。

【问题讨论】:

  • 感觉有点像你在要求别人为你写一个函数,这并不是 Stack Overflow 应该如何工作的。如果您编写的函数不起作用,那么您应该在答案中包含它,以及它不起作用的方式。然后您可能会收到更多回复。
  • 我已经编辑了我的问题以添加我正在研究的解决方案。谢谢。
  • 这看起来是一个不错的工作解决方案。由于看起来您使用的是 ES6 语法,因此您可以使用 Javascript mapfor...infind 在不使用 lodash 的情况下重写它,但如果您不想依赖 lodash,我只会这样做全部。一旦你接受了依赖,你就应该尽其所能地使用它。

标签: javascript object merge lodash


【解决方案1】:

一些可能的小改进

既然你问是否可以改进你写的算法,我试着做一些改变。

  • 我将函数命名为从 testcase2 开始,因为我认为您的函数是 testcase1。
  • 请原谅我,因为为了使测试独立于 React、Babel 和/或 Typescript,我将 JSX 语法转换为更简单的字符串连接。
  • 为了使函数更有用,我想您还希望展平结果数组并从集合中清除任何虚假值,以获得易于使用的数据格式。

我可以在浏览器中快速尝试这些功能吗?

当然!我实际上制作了一个 Codepen,您可以直接在浏览器中尝试这两种实现,只需记住打开浏览器控制台查看测试结果!这是链接:https://codepen.io/jhack_jos/pen/gOLYzvJ

两种可能的实现方式

使用 .flattenDeep

function testcase2(data)
{
    const riskCategory = data.risks;
    const riskDetails = data.riskDetails;
    return _.chain(riskCategory)
            .map( category => {
                return _.map(category, (risk, key) => {
                    return _.map(risk, (item, index) =>
                        {
                          const details = _.find(riskDetails, [key, item]);
                          return details &&
                            "<tr key=" + index + ">" +
                            "<td> " + item + "</td>" +
                            "<td> " + details.affected_people + "</td>" +
                            "<td> " + details.affected_wildlife + "</td>" +
                            "</tr>";
                        });
                  });
            })
           .flattenDeep()
           .compact()
           .value();
}

使用 .flatMap

function testcase3(data)
{
    const riskCategory = data.risks;
    const riskDetails = data.riskDetails;
    return _.chain(riskCategory)
            .flatMap( category => {
                return _.flatMap(category, (risk, key) => {
                    return _.map(risk, (item, index) =>
                        {
                          const details = _.find(riskDetails, [key, item]);
                          return details &&
                            "<tr key=" + index + ">" +
                            "<td> " + item + "</td>" +
                            "<td> " + details.affected_people + "</td>" +
                            "<td> " + details.affected_wildlife + "</td>" +
                            "</tr>";
                        });
                  });
            })
           .compact()
           .value();
}

详细说明

.flattenDeep、.flatMap 和 Monads

您需要扁平化数据吗?

  1. 您当然可以使用.flattenDeep 来删除使用多个.maps 生成的所有嵌套
  2. 然而,Lodash 为您提供了一个更好的方法:_.flatMap,这可能会导致执行时间稍快,所以我们不妨利用它。
  3. 如果你对the Monad buzzword感兴趣,你应该知道这实际上与Monads的概念有关,即使这里我们没有使用.flatMap来启用函数组合。事实上,最简单形式的 Monad 是实现.flatMap 的对象。长话短说,在地图之后展平集合的需求比人们最初可能想到的更具吸引力,并为许多可能性打开了大门。

其他注意事项

  • _.find 函数已经将_.matchesProperty 包含在语法_.find(array, [key, value])
  • 如果可能,最好避免在函数中使用多个 return 语句,这样更容易思考算法和重构
  • 使用&amp;&amp; 运算符,如果detailsundefined,我们可以返回undefined。否则返回右边的表达式。
  • 我看到你正在使用const,从而达到了不变性。太好了,事实上您也可以将details 变量设为const
  • 您可以使用_.compact 函数快速删除所有包含错误值的数组元素,例如false, null, 0, "", undefined, and NaN

感谢您的阅读!

我随时为您服务,您是否需要任何进一步的详细信息,或者代码与您要查找的内容不匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 2016-06-12
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    相关资源
    最近更新 更多