如何重构代码以减少嵌套循环的数量?

时间:2018-10-09 15:31:29

标签: javascript performance refactoring readability

这是一个帮助程序函数,它将类似对象的数组转换为实际数组,然后循环遍历可迭代对象,并将列表中的每个值提供给回调函数:

var each = function(iterable, callback) {
  iterable = Array.prototype.concat.apply([], iterable);
  for(var i = 0; i < iterable.length; i++) {
    callback.apply(iterable[i], [iterable[i], i]);
  }
  return iterable;
};

在这里,我正在使用上述的辅助函数来遍历数组:

var found = [];
each(arguments, function(argument) {
  each(argument.split(","), function(selector) {
    each(handle(selector), function(element) {
      if(found.indexOf(element) < 0) {
        found.push(element);
      }
    });
  });
});

第一个循环遍历参数。第二个循环拆分选择器,第三个循环遍历请求的元素,并将它们添加到found数组中(如果尚未添加)。

注意handle函数使用选择器(字符串)并使用document.querySelectorAll返回元素列表。

此脚本有效,但问题是可读性和性能。

当许多参数包含多个(〜5-10)逗号分隔的选择器,然后由handle函数分别处理时,就会出现性能问题。

我通过使用类而不是id来解决此问题。

接着是可读性问题,我试图通过将第二个循环移到父循环之外来解决此问题,但这需要创建更多变量,并且唯一的区别是更改了 where each循环的存在,使得有更多的代码需要阅读,从而使可读性更加糟糕。

问题:如何重构代码以减少嵌套循环的数量?

此外,是否有必要进行第一个循环?如果不使用它,我将如何遍历参数以拆分它们以获取每个单独的选择器?我知道split方法是String类型的,不能在数组上调用。

注意:我使用的是普通JavaScript,不包含任何库,框架或外部脚本。

2 个答案:

答案 0 :(得分:4)

您似乎希望收集一些出现在某些顺序数据源中的值,例如

["A,B", "C,A,D", "A", "C,E,B"]

放入(无重复项),例如

{"A", "B", "C", "D", "E"}

您可以在没有任何这样的第三方库(无需担心性能可读性)的情况下使用三个嵌套循环来做到这一点:

const s = new Set();
for (let x of arguments) {
    for (let g of x.split(",")) {
        for (let i of g) {
            s.add(i);
        }
    }
}

从功能上来说,您可以将那整个事情简化为:

new Set(arguments.join().split(','))

这当然假设您的选择器中没有逗号。

这里列表不是真正嵌套的,因为您需要三步来完全处理原始列表。细分:

  • 原文:[ 'A,B', 'C,A,D', 'A', 'C,E,B' ]
  • 加入后:'A,B,C,A,D,A,C,E,B'
  • 拆分后:[ 'A', 'B', 'C', 'A', 'D', 'A', 'C', 'E', 'B' ]
  • 设置后:Set { 'A', 'B', 'C', 'D', 'E' }

我认为即使在循环情况下,您也具有线性复杂度,因为您实际上是在原始数组上进行了三遍传递。并非每一遍都触及每个元素,因此尽管在原始情况下看起来像三次复杂,您应该很好,但是如果情况不好,请考虑进行概要分析。

答案 1 :(得分:1)

您可以加入然后重新分割参数,并使用三元运算符减少行数:)

"{"ErrorMessage":null,"UserBo":{"GateCollection":{"GateBosList":[]},"Status":0,"DlEd":"\/Date(1541278800000)\/","DlSd":"\/Date(1520715600000)\/","DlValue":"01:00","IsDl":true,"MobileIMEINo":null,"BranchId":0,"BranchName":null,"BUtcOffSt":"(UTC-08:00) Pacific Time (US \u0026 Canada)","UtcOffSt":"-8:0","IsDaylightSaving":false,"UserId":2031898,"CompanyId":3,"FirstName":"Yerandy","ChartCode":null,"LastName":null,"Email":null,"UserName":"YERANDY","Password":"123","WorkPhone":null,"WorkPhoneExt":null,"HomePhone":null,"CellNumber":null,"Fax":null,"DateCreated":"\/Date(-62135596800000)\/","LastLogin":"\/Date(-62135596800000)\/","IsAuthanticated":false,"IsSelected":false,"MobileUserStatus":null,"UserBosCollection":{"UserBosList":[]},"UserRoleBosCollection":{"RoleBosList":[{"CompanyId":3,"RoleId":6837,"Name":"Customer","Description":"Customer","CreatedBy":null,"Status":0,"ZonesList":{"ZoneBosList":[]},"UsersList":{"UserBosList":[]},"IsSelected":false},{"CompanyId":3,"RoleId":6838,"Name":"Carrier","Description":"Carrier","CreatedBy":null,"Status":0,"ZonesList":{"ZoneBosList":[]},"UsersList":{"UserBosList":[]},"IsSelected":false},{"CompanyId":3,"RoleId":2027893,"Name":"Order Entry","Description":"Order entry module","CreatedBy":"JAY","Status":0,"ZonesList":{"ZoneBosList":[]},"UsersList":{"UserBosList":[]},"IsSelected":false},{"CompanyId":3,"RoleId":2027898,"Name":"Dispatch \u0026 Order Entry","Description":"Dispatch \u0026 Order Entry","CreatedBy":"JAY","Status":0,"ZonesList":{"ZoneBosList":[]},"UsersList":{"UserBosList":[]},"IsSelected":false},{"CompanyId":3,"RoleId":2027899,"Name":"Order entry, Dispatch \u0026 Billin","Description":"Order entry, Dispatch \u0026 Billin","CreatedBy":"JAY","Status":0,"ZonesList":{"ZoneBosList":[]},"UsersList":{"UserBosList":[]},"IsSelected":false}]},"Company":{"CompanyLogo":null,"ReportLogo":null,"CompanyId":null,"IsQbposting":null,"IsEnableSsl":0,"IsUseDefaultCredentials":0,"SmtpPort":null,"SmtpHost":null,"InvoiceRemarks":null,"Name":null,"IsSelected":false,"DisplayName":null,"Description":null,"Status":0,"Res1":null,"Res2":null,"Res3":null,"CompanyCode":null,"Postal_Address":null,"Street_Address":null,"City":null,"State":null,"Zip":null,"Phone":null,"Fax":null,"Email":null,"Greetings":null,"FiscalYear":null,"TaxNo":null,"MasterUserName":null,"MasterUserPassword":null,"BranchesList":{"Branches":[]}},"CarrierId":null,"CustomerId":{"CustomerPdfBoList":null,"CustomerDocumentsBosList":null,"CustomerDocumentBo":null,"CustomerPhoneExt":null,"CustomerTypeBo":null,"CustomerService":null,"CustomerServiceList":null,"CompanyId":null,"IsSelected":false,"CustomerId":6484,"CustomerCode":null,"CustomerName":"YC INTERNATIONAL GROUP INC","CustomerType":0,"TradingPartner":null,"SynchronizationtypeId":null,"Phone":null,"Fax":null,"IsAutoFax":null,"Email":null,"CustomerBranchId":0,"CSR":null,"StartOfBusiness":"\/Date(-62135596800000)\/","Description":null,"Status":0,"PaymentTermId":0,"Res1":null,"Res2":null,"Res3":null,"Res4":null,"Res5":null,"CustomerSalesRep":null,"CustomerAddresses":{"AddressBosList":[]},"CustomerAddress":null,"CustomerContacts":{"ContactList":[]},"CustomerContact":null,"User":null,"CustomerTypeName":null,"CustomerPaymentTermsBo":null,"Site":null,"CustomerServiceCollection":null},"DeviceId":null,"Log":null,"UserImage":"Default.png","DispatchSettings":null},"AlertCount":0,"CacheContext":null,"DtoStatus":1,"Message":null,"CompanyId":null,"BranchId":null,"BaseFilterList":null,"StartDate":"\/Date(-62135596800000)\/","EndDate":"\/Date(-62135596800000)\/","Day":null}"