使用lodash

时间:2018-02-27 17:50:29

标签: javascript object merge lodash

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

对象一

{"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就可以了。

编辑:

我认为,出于我的目的,我并不需要将两者合并为一个对象,但可以通过第一个中的每个项目并在第二个中找到匹配。这是我提出的对我有用的片段:

        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帮助我让生活变得更轻松,但我不想太依赖它。

1 个答案:

答案 0 :(得分: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 删除使用多个 .map 生成的所有嵌套
  2. 然而,Lodash 为您提供了一种更好的方法:_.flatMap,这可能会导致执行时间稍快一些,因此我们不妨利用它。
  3. 如果您对 the Monad buzzword 感兴趣,您应该知道这与 Monads 的概念有效相关,即使在这里我们不使用 .flatMap 来启用函数组合。事实上,Monad 最简单的形式是一个实现 .flatMap 的对象。长话短说,在地图之后将馆藏扁平化的需求比人们最初想到的更具吸引力,并开启了许多可能性。

其他注意事项

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

感谢您的阅读!

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