【问题标题】:Combine nested arrays and remove duplicates合并嵌套数组并删除重复项
【发布时间】:2020-12-10 19:41:06
【问题描述】:

我将如何组合这些数组集以使它们连接在一起并且没有重复值?

不确定 lodash 是否对此有帮助,我发现的大多数其他答案都是基于扁平数组,但我的数据集的结构将它们嵌套。

感谢您的帮助!

let arr1 = [
  ["name", "id", 'age'],
  ["Susan", "3", '20'],
  ["John", "1", '21'],
  ["Bob", "2", '23'],
  ["Ben", "4", '20']
];

let arr2 = [
  ["name", "id", 'height'],
  ["Bob", "2", '50'],
  ["John", "1", '45'],
  ["Ben", "4", '43'],
  ["Susan", "3", '48'],
];

let arr3 = [
  ["name", "id", 'parent'],
  ["Bob", "2", 'yes'],
  ["John", "1", 'yes'],
];


//desired output
// [
//   ['name', 'id', 'age', 'height', 'parent'],
//   ["Susan", "3", '20', '48', ''],
//   ["John", "1", '21', '45', 'yes'],
//   ["Bob", "2", '23', '50', 'yes'],
//   ["Ben", "4", '20', '43', '']
// ]

【问题讨论】:

    标签: javascript arrays reactjs nested lodash


    【解决方案1】:

    您可以在原生 JavaScript 中做到这一点。首先使用reduce方法将所有三个数组变成对象。然后再次使用 reduce 方法获取唯一的合并对象。最后,将对象变成一个数组。

    const arr1 = [
      ['name', 'id', 'age'],
      ['Susan', '3', '20'],
      ['John', '1', '21'],
      ['Bob', '2', '23'],
      ['Ben', '4', '20'],
    ];
    
    const arr2 = [
      ['name', 'id', 'height'],
      ['Bob', '2', '50'],
      ['John', '1', '45'],
      ['Ben', '4', '43'],
      ['Susan', '3', '48'],
    ];
    
    const arr3 = [
      ['name', 'id', 'parent'],
      ['Bob', '2', 'yes'],
      ['John', '1', 'yes'],
    ];
    
    const makeObject = (arr) => {
      const props = arr.slice(0, 1).flat();
      return arr.slice(1).map((x) => {
        return props.reduce((prev, c, i) => {
          const p = prev;
          p[c] = x[i];
          return p;
        }, {});
      });
    };
    
    const objArray = Object.values(
      [...makeObject(arr1), ...makeObject(arr2), ...makeObject(arr3)].reduce(
        (prev, c) => {
          const p = prev;
          const key = c.id;
          if (!p[key])
            p[key] = {
              ...{ name: '', id: '', age: '', height: '', parent: '' },
              ...c,
            };
          else p[key] = { ...p[key], ...c };
          return p;
        },
        {}
      )
    );
    const ret = objArray.map((x) => Object.values(x));
    ret.unshift(Object.keys(objArray[0]));
    console.log(ret);

    【讨论】:

      【解决方案2】:

      使用 lodash flattenuniq

      Flatten 将数组合并为一个扁平数组。

      _.uniq(_.flatten([arr1, arr2, arr2));
      

      现在回答了您问题的标题和文本,但从您想要的输出来看,您的处境很艰难。我所概述的内容不会产生这样的结果。

      您可以考虑使用 Lodash 的 merge 函数,但您正在做的事情是使用对象而不是数组更容易。

      【讨论】:

      • 我同意你的看法......这会很艰难?
      • 您是否考虑过将您拥有的数组制作成对象?这样做然后使用 lodash 的 mergeWith 可能是你最好的选择。
      【解决方案3】:

      我建议先创建一个对象。 ES6 语法允许您在几行内完成。这也解决了统一问题。

      const addData = ([head, ...data], obj = {}) => (
        data.reduce((acc, [name, id, value]) => ({
          ...acc,
          [id]: {
            ...acc[id],
            name, [head[2]]: value
          }
        }), obj)
      )
      
      // -------
      
      const arr1 = [
        ["name", "id", 'age'],
        ["Susan", "3", '20'],
        ["John", "1", '21'],
        ["Bob", "2", '23'],
        ["Ben", "4", '20']
      ];
      
      const arr2 = [
        ["name", "id", 'height'],
        ["Bob", "2", '50'],
        ["John", "1", '45'],
        ["Ben", "4", '43'],
        ["Susan", "3", '48'],
      ];
      
      const arr3 = [
        ["name", "id", 'parent'],
        ["Bob", "2", 'yes'],
        ["John", "1", 'yes'],
      ];
      
      
      let indexedObj = {}
      indexedObj = addData(arr1, indexedObj)
      indexedObj = addData(arr2, indexedObj)
      indexedObj = addData(arr3, indexedObj)
      
      console.log(indexedObj)

      然后使用mr hr的数组创建方法。

      【讨论】:

        【解决方案4】:

        通过将行转换为对象并使用 Array.reduce() 和 Map 合并它们来组合表(以保留原始顺序)。保留标题,并使用_.union()(或集合)将它们组合起来。然后返回一个包含组合标题的数组,并使用Array.mpa() 和组合标题将正文行转换为数组。

        // convert table rows to objects
        const tableRowsToObjects = ([head, ...body]) => [head, body.map(row => _.zipObject(head, row))]
        
        // combine tables' headers & bodies
        const combineTables = tables => {
          const header = _.union(..._.map(tables, _.head))
        
          const body = Array.from(
            tables
              .flatMap(([, rows]) => rows)
              .reduce((acc, row) => acc.set(row.id, { ...acc.get(row.id), ...row }), new Map)
              .values()
          )
        
          return [header, body]
        }
        
        // convert tables to objects, merge them, and then convert back to rows
        const mergeTables = (...tables) => {
          const [header, body] = combineTables(tables.map(tableRowsToObjects))
          
          return [
            header,
            ...body.map(row => header.map(col => row[col] ?? ''))
          ];
        }
        
        const arr1 = [["name","id","age"],["Susan","3","20"],["John","1","21"],["Bob","2","23"],["Ben","4","20"]];
        const arr2 = [["name","id","height"],["Bob","2","50"],["John","1","45"],["Ben","4","43"],["Susan","3","48"]];
        const arr3 = [["name","id","parent"],["Bob","2","yes"],["John","1","yes"]];
        
        const result = mergeTables(arr1, arr2, arr3);
        
        console.log(result);
        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-15
          • 2011-01-09
          • 2017-06-22
          相关资源
          最近更新 更多