【问题标题】:remove nested foreach loops删除嵌套的 foreach 循环
【发布时间】:2018-09-21 18:36:51
【问题描述】:

在我的代码中,我使用了两个 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,如果 name 键的值存在于 Channel 键的值中,则它从 obj3 中选择 Accountcode 和 State 并将它们推送到 obj2 的调用数组中。 这是输出数组:-

    [ {
  "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 函数来做这件事,但我真的不确定这是否可以提高性能。 如果您有更好的建议,请告诉我。

【问题讨论】:

  • 通过索引访问数组,这样你就可以使用 for 迭代两个数组
  • 如果name 存在于Channel 中,它是否在可预测的位置 - 第一个正斜杠之后的数字?
  • reduce 与此处的forEach 相同。您真正需要的是按名称查找表。
  • @Bergi 是的,我同意你的看法。
  • @CertainPerformance 是

标签: javascript performance optimization


【解决方案1】:

由于names 位于Channel 内的一个可预测位置,您可以从obj3 最初构建一个由names 索引的对象,然后只需使用括号表示法来获取您需要的数组, 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);

【讨论】:

    【解决方案2】:

    我尝试使用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

    【讨论】:

    • 这与 OP 的原始代码存在相同的问题 - filtermap 都具有 O(n) 复杂度,所以这是 O(n^2) 复杂度总体而言,没有任何改进。
    【解决方案3】:

    希望这会有所帮助。我在 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);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 2023-03-09
      • 2019-07-13
      • 2016-05-28
      • 2020-03-17
      相关资源
      最近更新 更多