删除嵌套的foreach循环

时间:2018-09-21 09:41:28

标签: javascript performance optimization

在我的代码中,我使用了两个forEach循环。但是为了优化我的代码,已指示我不要在forEach循环内使用forEach循环。 所以我不想遍历第二个数组obj3。我只想在不使用内部forEach循环的情况下将值放在某个位置。 这是我的代码:-

var obj2 = [{
  "name": "4134",
  "calls": [

  ]
}]

    var obj3 = [{ Channel: 'SIP/4134-0004462a',
        State: 'Up',
        Accountcode: '7013658596'},
      { Channel: 'SIP/4334-sa',
        State: 'Up',
        Accountcode: '07717754702',
      }]


var function = (obj2, obj3) => {
    obj2.forEach((a) =>
      obj3.forEach((b) => {
        if (b.Channel.includes(a.name)) a.calls = (a.calls || []).concat(Object.assign({}, { MobileNo: b.Accountcode, Status : b.State}));

      })
    );
};

function(obj2, obj3);

上面的代码循环遍历obj2和obj3,如果在Channel密钥的值中存在名称密钥的值,则它将从obj3中选择Accountcode和State并将它们推入obj2的calls数组中。 这是输出数组:-

    [ {
  "name": "4134",
  "calls": [
    {
      "MobileNo": "7013658596",
      "Status": "Up"
    }
  ]
}]

我到目前为止所做的事情

var func = (obj2, obj3) => {

var channelArr = [];
const Channels = obj3.reduce((acc, curVal) => {
  obj2.forEach((item)=>{
    if(curVal.Channel.includes(item.name)){
      item.calls.push({'MobileNo':curVal.Accountcode,'Status': curVal.State})
    }
  })
  return obj2;
}, [])

};

我尝试使用reduce函数来执行此操作,但是我真的不确定这是否可以提高性能。 如果您有更好的建议,请告诉我。

3 个答案:

答案 0 :(得分:2)

由于name位于Channel内的可预测位置,因此您可以从name开始构建一个由obj3 s索引的对象,然后只需使用方括号即可表示法来获取所需的数组,O(n)

var obj2 = [{
  "name": "4134",
  "calls": [
  ]
}];
var obj3 = [{
    Channel: 'SIP/4134-0004462a',
    State: 'Up',
    Accountcode: '7013658596'
  },
  {
    Channel: 'SIP/4334-sa',
    State: 'Up',
    Accountcode: '07717754702',
  }
]

const objsByName = obj3.reduce((a, item) => {
  const { Channel } = item;
  const name = Channel.match(/\/(\d+)/)[1];
  if (!a[name]) a[name] = [];
  a[name].push(item);
  return a;
}, {});
obj2.forEach(({ name, calls }) => {
  calls.push(...objsByName[name]);
});
console.log(obj2);

答案 1 :(得分:1)

我尝试使用filtermap,请检查是否适合您。

const result = obj2.map(a => {
  const foundAll = obj3.filter(
    ({ Channel, Accountcode, State }) =>
      Channel.includes(a.name) && { Accountcode, State }
  );
  return {
    name: a.name,
    calls: [...a.calls, foundAll]
  };
});
console.info(result);

找到工作Bin here

答案 2 :(得分:1)

希望这会有所帮助。我已经在obj3的帮助下创建了类似于结构的查找表。然后在遍历obj2时仅检查查找表中是否存在名称,如果存在,则将某个对象分配给calls

var obj2=[{name:"4134",calls:[]}],obj3=[{Channel:"SIP/4134-0004462a",State:"Up",Accountcode:"7013658596"},{Channel:"SIP/4334-sa",State:"Up",Accountcode:"07717754702"}];

var fun = (obj2, obj3) => {
  //creating temp object which conatin name as key and index as value from obj2
  var temp={};
  obj3.forEach((b,i)=>{
    var myRegexp = /\/(\d+)/g;
    var name=myRegexp.exec(b.Channel);
    temp[name[1]]=i;
  });
  
  obj2.forEach(a => {
    if(temp[a.name] !== undefined) {  //if temp object contain key then we need to merge this object
      var b = obj3[temp[a.name]];
      a.calls =  (a.calls || []).concat(Object.assign({}, { 
                     MobileNo: b.Accountcode, 
                     Status : b.State
                 }));
    }
  });
  console.log(obj2);
}
fun(obj2,obj3);