在Javascript中合并具有相同键和不同长度的两个数组

时间:2018-03-09 21:47:42

标签: javascript arrays

我正在尝试解决问题,但无法弄清楚如何做到这一点。 我有两个数组:

var arr1 = [
     {Week: "WK1", CreatedTickets: 1}, {Week: "WK3", CreatedTickets: 12}, 
     {Week: "WK2", CreatedTickets: 3}, {Week: "WK5", CreatedTickets: 5}
];

var arr2 = [
     {Week: "WK1", ClosedTickets: 4}, {Week: "WK6", ClosedTickets: 40},
     {Week: "WK3", ClosedTickets: 33}, {Week: "WK2", ClosedTickets: 2}
 ];

预期的产出将是和周也应该是有序的。

var output = [
     {Week: "WK1", CreatedTickets: 1, ClosedTickets: 4}, 
     {Week: "WK2", CreatedTickets: 3, ClosedTickets: 2},
     {Week: "WK3", CreatedTickets: 12, ClosedTickets: 33},
     {Week: "WK5", CreatedTickets: 5, ClosedTickets: 0},
     {Week: "WK6", CreatedTickets: 0, ClosedTickets: 33}
];

请帮我解决这个问题。非常感谢。

杰米

3 个答案:

答案 0 :(得分:0)

要达到预期效果,请使用以下选项,

获得准确输出的两个循环

  1. 以下面的格式创建对象的第一个循环

    {
            “WK1”:{             “CreatedTickets”:1,             “ClosedTickets”:4         },
            “WK2”:{             “CreatedTickets”:3,             “ClosedTickets”:2         },
            “WK3”:{             “CreatedTickets”:12,             “ClosedTickets”:33         },
            “WK5”:{             “CreatedTickets”:5,             “ClosedTickets”:0         },
            “WK6”:{             “CreatedTickets”:0,             “ClosedTickets”:33         }
        }

  2. 用于将上述临时对象转换为输出数组

    的第二个循环

    [
          {Week:“WK1”,CreatedTickets:1,ClosedTickets:4},
          {Week:“WK2”,CreatedTickets:3,ClosedTickets:2},
          {Week:“WK3”,CreatedTickets:12,ClosedTickets:33},
          {Week:“WK5”,CreatedTickets:5,ClosedTickets:0},
          {Week:“WK6”,CreatedTickets:0,ClosedTickets:33}
    ];

  3. JS

    var output =[];//output array
    var temp = {};//temp object
    
    var arr1 = [
         {Week: "WK1", CreatedTickets: 1}, {Week: "WK3", CreatedTickets: 12}, 
         {Week: "WK2", CreatedTickets: 3}, {Week: "WK5", CreatedTickets: 5}
    ];
    
    var arr2 = [
         {Week: "WK1", ClosedTickets: 4}, {Week: "WK6", ClosedTickets: 40},
         {Week: "WK3", ClosedTickets: 33}, {Week: "WK2", ClosedTickets: 2}
     ];
    
    var concatArr = arr1.concat(arr2)
    
    
    
    for(var o of concatArr){
      if(Object.keys(temp).indexOf(o.Week)==-1){
       temp[o.Week] ={}
       o.ClosedTickets?temp[o.Week].ClosedTickets = o.ClosedTickets:temp[o.Week].ClosedTickets = 0
       o.CreatedTickets?temp[o.Week].CreatedTickets = o.CreatedTickets:temp[o.Week].CreatedTickets = 0
      }else{
       o.ClosedTickets?temp[o.Week].ClosedTickets = temp[o.Week].ClosedTickets + o.ClosedTickets:temp[o.Week].ClosedTickets
       o.CreatedTickets?temp[o.Week].CreatedTickets = temp[o.Week].CreatedTickets + o.CreatedTickets:temp[o.Week].CreatedTickets
     }
    }
    
    for( var key of Object.keys(temp)){
      output.push({
        Week:key,
        CreatedTickets:temp[key].CreatedTickets,
        ClosedTickets:temp[key].ClosedTickets
      })
    }
    
    console.log(output)

    代码示例 - https://codepen.io/nagasai/pen/RMNVvQ?editors=1010

答案 1 :(得分:-1)

您可以映射(使用reduce)初始数组以更快地访问其键,然后使用forEach执行循环以构建所需的结果。

现在,使用sort值(只是数字)执行Week结果数组。

var arr1 = [{Week: "WK1", CreatedTickets: 1}, {Week: "WK20", CreatedTickets: 7}, {Week: "WK3", CreatedTickets: 12}, {Week: "WK2", CreatedTickets: 3}, {Week: "WK5", CreatedTickets: 5}],
    arr2 = [{Week: "WK1", ClosedTickets: 4}, {Week: "WK6", ClosedTickets: 40},{Week: "WK3", ClosedTickets: 33}, {Week: "WK2", ClosedTickets: 2}],
    // Convert to something like this:
    //  {
    //    "WK1": {
    //      "Week": "WK1",
    //      "CreatedTickets": 1
    //    },
    //    "WK20": {
    //      "Week": "WK20",
    //      "CreatedTickets": 7
    //    },
    //  }
    //
    // This is to speed up the access and comparisons.
    //
    map1 = arr1.reduce((a, o) => ({...a, ...{[o.Week]: o}}), {}),
    map2 = arr2.reduce((a, o) => ({...a, ...{[o.Week]: o}}), {});
 
 // Now let's loop the keys of the previously mapped 'map1'.
 Object.keys(map1).forEach(k => {
  if (map2[k]) {
    // This is to avoid the values ("WK1", "WK2", and so on.) 
    // because map1 already has that value.
    delete map2[k].Week; 
    
    // Will generate something like this:
    // { 
    //   WK1: {
    //     "Week": "WK1",
    //     "CreatedTickets": 1,
    //     "ClosedTickets": 4
    //   }
    // }
    map1[k] = { ...map1[k], ...map2[k] };        
  } else {
    // Will generate something like this:
    // { 
    //   WK1: {
    //     "Week": "WK1",
    //     "CreatedTickets": 7,
    //     "ClosedTickets": 0 // To initialize qith zero because is an object that doesn't exists in map2
    //   }
    // }
    map1[k] = { ...map1[k], ...{CreatedTickets: map1[k].CreatedTickets, ClosedTickets: 0} };    
  }
 });
 
 // Now the same forEach for the map2 to complete with the missing objects (weeks) in map1
 Object.keys(map2).forEach(k => {
  if (!map1[k]) {
    map1[k] = { ...map1[k], ...{Week: map2[k].Week, CreatedTickets: 0, ClosedTickets: map2[k].ClosedTickets} };    
  }
 });
 
 // Justa a sort
 var sorted = Object.values(map1).sort((a,b) => a.Week.replace(/[a-z]/gi, '') - b.Week.replace(/[a-z]/gi, ''));
 console.log(sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:-1)

如果使用ESNext功能,您可以使用一些快捷方式,但由于您使用的是var而不是let / const,我只假设是ES5。

以下是一个简单的解决方案。

var arr1 = [
     {Week: "WK1", CreatedTickets: 1}, 
     {Week: "WK3", CreatedTickets: 12}, 
     {Week: "WK2", CreatedTickets: 3},
     {Week: "WK20", CreatedTickets: 7},
     {Week: "WK5", CreatedTickets: 5}
];

var arr2 = [
     {Week: "WK1", ClosedTickets: 4}, 
     {Week: "WK6", ClosedTickets: 40},
     {Week: "WK3", ClosedTickets: 33},
     {Week: "WK2", ClosedTickets: 2}
];

//first lets make a copy of arr1
var output = arr1.slice();

//now loop arr2, and see if exists in ouput or not
arr2.forEach(function (item) {
  //lets find in arr1
  var f = output.find(function(i) { return item.Week === i.Week; });
  if (f) {
    //ok found lets update
    f.ClosedTickets = item.ClosedTickets;
  } else {
    //not found lets add
    output.push(item);
  }
});

//ok if we want 0, for OpenTickets and ClosedTickets if none found
output.forEach(function (item) {
  item.ClosedTickets = item.ClosedTickets | 0;
  item.CreatedTickets = item.CreatedTickets | 0;
});

//finally lets's sort
//one gotcha, sorting by WK1,WK2,WK10 etc in string sort would give
//WK1, WK10, WK2.. so we will use regex to extract just the wk part
//convert to integer and then sort

var regexnum = /\d+/;

function numWk(s) {
  return parseInt(regexnum.exec(s.Week)[0], 10);
}

output.sort(function (a,b) { return numWk(a) - numWk(b); });

console.log(output);