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

问题描述 投票:3回答:2

这是一个辅助函数,它将像对象这样的数组转换为实际数组,然后循环遍历iterable,将列表中的每个值提供给回调函数:

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来修复此问题。

然后出现了可读性问题,我试图通过将第二个循环移到父循环之外来解决这个问题,但这需要创建更多变量,它唯一的区别就是改变了each循环的位置,这使得可读性更差,鉴于有更多的代码可供阅读。

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

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

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

javascript performance refactoring readability
2个回答
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:Set { 'A', 'B', 'C', 'D', 'E' }之后

我认为即使在循环情况下你也有线性复杂性,因为你实际上是在原始数组上进行三次传递。并非每个过程都触及每个元素,因此虽然它看起来像原始情况下的立方复杂性,但您应该没问题,但如果事情看起来很糟糕,请考虑分析。


1
投票

你可以加入然后resplit参数并使用三元运算符来减少行数:)

var found = [];
each(arguments.join(",").split(","), function(selector) {
  each(handle(selector), function(element) {
    return (found.indexOf(element) < 0) ? found.push(element) : null;
  });
});
© www.soinside.com 2019 - 2024. All rights reserved.