如何通过使用键,值对将具有两个不同大小的两个对象数组合并到一个数组中?

时间:2019-03-06 00:15:50

标签: javascript angular typescript lodash

我有两个对象数组,它们以JSON格式显示:

   {
  "Arr1":
   [
    { "_id": "firstSub1", "count": 1, "price": 4 },
    { "_id": "firstSub2", "count": 2, "price": 7 },
    { "_id": "firstSub3", "count": 3, "price": 1 }
    { "_id": "firstSub4", "count": 4, "price": 1 }
   ],

    "Arr2":
     [
      { "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1 },
      { "name": "firstSub2"  "date": 12 / 22 / 2011, "type": sometype2 },
      { "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3 }
      { "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 }
    ]
//Desired Output
    "finalArray":
     [
      { "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1, "count": 1, "price": 4 },  
      { "name": "firstSub2"  "date": 12 / 22 / 2011, "type": sometype2, "count": 2, "price": 7 },
      { "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3, "count": 3, "price": 1 },
      { "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 },
      { "_id": "firstSub4", "count": 4, "price": 1 }
          ]   

}

我需要比较第一个数组中的_id,看看Arr2中是否与name匹配,如果_id === name,则将它们匹配。

我尝试使用lodash及其undescores和映射功能,如下所示:

  mergeArray() {
    .... //pulling data

    let Arr1 = data['Arr1Data'];
    let Arr2 = data['Arr2Data'];

    let finalArray = Arr2.map((e, _) =>
      (_ = Arr1.find((q) => e.name === q._id)) ?
        { ...e, ..._ } : e)
    console.log(finalArray)
  }

来自Arr2的所有数据都返回并仅与一半数据Arr1合并,我的数据未返回所需的输出...我如何映射这两个数组并具有并集和交集?

4 个答案:

答案 0 :(得分:1)

使用香草Js,您可以从两个数组中获取唯一的_idname数组,循环遍历,并从两个数组中将与当前id相匹配的对象加入迭代:

idname s组成的重复数组:

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

循环连接两个数组中的元素:

const result = ids.map(e => ({
  ...Arr1.find(o => o._id === e),
  ...Arr2.find(o => o.name === e)
}))

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

const result = ids.map(e => ({
  ...Arr2.find(o => o.name === e),
  ...Arr1.find(o => o._id === e)
}))
console.log(result)

编辑: 您可以在.map()中调整返回的对象以删除属性(例如_id):

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

const result = ids.map(e => {
  const obj = {
    ...Arr2.find(o => o.name === e),
    ...Arr1.find(o => o._id === e)
  }
  
  if(obj.name && obj._id) delete obj._id;
  
  return obj;
})
console.log(result)

答案 1 :(得分:0)

一种解决方案是使用以Set myOutput = Sheets(ActiveSheet.Name) myOutput.PageSetup.Orientation = xlLandscape myOutput.PageSetup.TopMargin = 1.91 myOutput.PageSetup.BottomMargin = 1.91 myOutput.PageSetup.LeftMargin = 0.64 myOutput.PageSetup.RightMargin = 0.64 myOutput.PageSetup.HeaderMargin = 0.76 myOutput.PageSetup.FooterMargin = 0.76 开头的accumulator等于Arr2JSON.parse(JSON.stringify(Arr2)))的副本,这样我们就不会对原始数组{{1 }}。现在,在Arr2上进行迭代时,如果找到匹配项,则使用Array.reduce()将相关属性添加到Arr1上的关联对象上,否则我们将整个对象放在{{ 1}}:

accumulator
accumulator

答案 2 :(得分:0)

您可以按name排序并比较i + 1索引名称,以验证i + 1索引和i索引是否应该合并或对象是否应该合并有一对要合并。

例如,按name排序意味着下一个对象/索引将是该对。

[{name: "firstSub1", count: 1}, {name: "firstSub1", date: "dd / mm / yyyy"}] // Pair found

[{name: "firstSub1", count: 1}, {name: "firstSub2", count: 1}] // There is no a pair

这是假设最多一对

let obj = {  "Arr1": [{      "_id": "firstSub1",      "count": 1,      "price": 4    },    {      "_id": "firstSub2",      "count": 2,      "price": 7    },    {      "_id": "firstSub3",      "count": 3,      "price": 1    },    {      "_id": "firstSub4",      "count": 4,      "price": 1    }  ],  "Arr2": [{      "name": "firstSub1",      "date": "05 / 20 / 1998",      "type": "sometype1"    },    {      "name": "firstSub2",      "date": "12 / 22 / 2011",      "type": "sometype2"    },    {      "name": "firstSub3",      "date": "09 / 23 / 2004",      "type": "sometype3"    },    {      "name": "firstSub9",      "date": "09 / 23 / 2004",      "type": "sometype9"    }  ]};

// All objects in one array.
let merge = [...obj.Arr2, 
             // The map is to change _id by name, this is used later.
             ...obj.Arr1.map(({_id, count, price}) => ({name: _id, count, price}))]
                  .sort((a, b) => a.name.localeCompare(b.name));

// This approach doesn't mutate the source objects.
let result = [];
for (let i = 0; i < merge.length;) {
  if (merge[i + 1] && merge[i + 1].name === merge[i].name) {
    result.push(Object.assign(Object.create(null), merge[i], merge[i + 1]));
    i++;
  } else result.push(merge[i]);
  i++;
}

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:0)

您可以使用lodash的_.flow()创建一个组合数组的函数,将它们按name_id分组(无论在对象上找到什么)。如果一个组包含多个项目,则该项目将合并到一个对象中,并且将省略_id属性。

const { flow, partialRight: pr, concat, groupBy, map, merge, has, head, omit } = _

const fn = flow(
  concat, // combine to a single array
  pr(groupBy, o => o.name || o._id), // group by the value of name or _id
  pr(map, o => o.length === 1 ? head(o) : _.omit( // if a group contains 2 items merge them, and remove _id
    merge({}, ...o),
    '_id'
  )),
)

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}]

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}]

const result = fn(Arr2, Arr1)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>