Как мне реорганизовать мой код, чтобы уменьшить количество вложенных циклов? - PullRequest
0 голосов
/ 09 октября 2018

Вот вспомогательная функция, которая преобразует массив, подобный объекту, в реальный массив, а затем перебирает итерацию, передавая каждое значение в списке функции обратного вызова:

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.

Я исправил это, используя классы вместо идентификаторов.

Затемвозникает проблема читабельности, которую я попытался исправить, переместив второй цикл за пределы родительского цикла, но это потребовало создания большего количества переменных, и единственное отличие, которое он сделал, было изменение , где цикл each был, что ухудшило читабельность, учитывая, что для чтения было больше кода.

Вопрос : Как я могу реорганизовать мой cОда уменьшить количество вложенных циклов?

Кроме того, необходимо ли иметь первый цикл?Если я не использую его, как я буду перебирать аргументы, чтобы разделить их, чтобы получить каждый отдельный селектор?Я знаю, что метод split предназначен для типа String и не может быть вызван для массивов.

ПРИМЕЧАНИЕ : я использую ванильный JavaScript, не включая библиотеки и фреймворкиили внешние скрипты.

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Вы можете присоединиться, затем разделить аргументы и использовать троичный оператор, чтобы уменьшить количество строк:)

var found = [];
each(arguments.join(",").split(","), function(selector) {
  each(handle(selector), function(element) {
    return (found.indexOf(element) < 0) ? found.push(element) : null;
  });
});
0 голосов
/ 09 октября 2018

Похоже, что вы хотите собрать ряд значений, которые появляются в некотором последовательном источнике данных, например

["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' }

Я думаю, что даже в случае цикла у вас есть линейная сложность, потому что вы делаете три прохода над исходным массивом.Не каждый элемент затрагивается на каждом проходе, поэтому, хотя в оригинальном случае это выглядит как кубическая сложность, вам должно быть в порядке, но подумайте о профилировании, если все выглядит плохо.

...