【问题标题】:How to get unique array from nested object with lodash如何使用 lodash 从嵌套对象中获取唯一数组
【发布时间】:2020-06-09 09:33:45
【问题描述】:

我的集合包含以下(对象数组):

[
    {
        id: 'id-1',
        uniqueName: 'operation-level-1',
        operations: [
            {
                name: 'operaion-1',
                label: 'operation-1-label'
            },
            {
                name: 'operaion-2',
                label: 'operation-2-label'
            }
        ]
    },
    {
        id: 'id-2',
        uniqueName: 'operation-level-2'
        operations: [
            {
                name: 'operaion-1',
                label: 'operation-1-label'
            },
            {
                name: 'operaion-3',
                label: 'operation-3-label'
            }
        ]
    }

]

我想得到一个唯一的操作名称和标签数组,如下所示

const result = [
    {
        name: 'operaion-1',
        label: 'operation-1-label'
    },
    {
        name: 'operaion-2',
        label: 'operation-2-label'
    },
    {
        name: 'operaion-3',
        label: 'operation-3-label'
    }
]

有人可以建议实现这一目标的最佳方法吗?

【问题讨论】:

  • 最好的方法是实现代码。你能展示一下你已经为此做了什么吗?

标签: javascript arrays object lodash


【解决方案1】:

没有lodash 也可以轻松完成。您可以先将数据扁平化,然后将 map 作为键值对,然后使用 Map 删除重复条目:

var data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];

var result =  [...new Map(data.flatMap(({operations})=>operations).map(k=>([k.name, k]))).values()];

console.log(result);

或者如果你不想使用Map,那么使用filter方法:

var data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];

var result = data.flatMap(({operations})=>operations).filter((val,i,self)=>self.findIndex(j=>j.name==val.name && j.label==val.label)==i);

console.log(result);

【讨论】:

    【解决方案2】:

    使用_.flatMap() 获取operations 的扁平数组,然后使用_.uniqBy() 仅获取具有唯一name 的项目:

    const data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
    
    const result =  _.uniqBy(
      _.flatMap(data, 'operations'),
      'name'
    );
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

    使用 lodash/fp,您可以使用 _.flow() 生成一个将 operations 展平的函数,然后通过 name 获取唯一值:

    const fn = _.flow(
      _.flatMap('operations'),
      _.uniqBy('name')
    )
    
    const data=[{ id: 'id-1', uniqueName: 'operation-level-1', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-2', label: 'operation-2-label' } ] }, { id: 'id-2', uniqueName: 'operation-level-2', operations: [ { name: 'operaion-1', label: 'operation-1-label' }, { name: 'operaion-3', label: 'operation-3-label' } ] }];
    
    const result = fn(data);
    
    console.log(result);
    <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

    【讨论】:

      【解决方案3】:

      不需要 loadash,一个简单的 Map 对象,将允许您抑制重复。

      const arr = [{
          id: 'id-1',
          uniqueName: 'operation-level-1',
          operations: [{
              name: 'operaion-1',
              label: 'operation-1-label'
            },
            {
              name: 'operaion-2',
              label: 'operation-2-label'
            }
          ]
        },
        {
          id: 'id-2',
          uniqueName: 'operation-level-2',
          operations: [{
              name: 'operaion-1',
              label: 'operation-1-label'
            },
            {
              name: 'operaion-3',
              label: 'operation-3-label'
            }
          ]
        }
      ];
      
      // Go thought the arr and add all the name/label into the map
      // Then use Array.from to reformate the Map into the wanted format
      const uniqueArr = Array.from(arr.reduce((tmp, {
        operations,
      }) => {
        operations.forEach(({
          name,
          label,
        }) => {
          tmp.set(name, label);
        });
      
        return tmp;
      }, new Map())).map(([name, label]) => ({
        name,
        label,
      }));
      
      console.log(uniqueArr);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多