Рекурсия с условиями, на основе массива данных

145
29 января 2020, 11:30

У меня формируется некая схема, по которой я хочу пройтись циклом и выполнить опеределённые условия для определённых операторов.

const arrWhereScheme = [{
  operator: 'and',
  item: [{
    method: 'eq',
    condition: {'name': 'Имя}
  }, {
    method: 'in',
    condition: {'count': [1,2,3]}
  }, {
    operator: 'or',
    item: [{
      method: 'eq',
      condition: {'name': 'Имя'}
    }, {
      method: 'gt',
      condition: {'startDate': "20.08.2017"}
    }]
  }]
}];

Содержимое схемы: объект (может быть много) содержащий поле operator и поля item (является массивом).
Элементы в item могут содержать в себе объект в котором есть поле method и condition, но так же item может содержать в себе повторный объект из поля operator и поля item (является массивом) и дальше суть повторяется, такое количество может быть досточно глубоким, но заранее не известно.

Когда подобная схема сформируется, мне необходимо пройтись по ней в цикле, и выполнить условия для нужных операторов. В данном объекте есть operator который будет вызывать опеределённый блок кода, а так же количество элементов.

arrWhereScheme.forEach(items => (
  if(items.operator === 'and'){
    item.item.forEach((inItem)=> (
      // Здесь будут выполняться условия если элементы содержат method и condition, 
      // но если появился объект с полем operator и item, то повторить конструкицю
      if(items.operator === 'and'){
        item.item.forEach((inItem)=> ()) 
      }
    ))
  }
  // Здесь конечно возможен не один if
));

Как реализовать такую рекурсию?

Answer 1
const arrWhereScheme = [/*...*/]; 
processScheme(arrWhereScheme); 
function processScheme(schm) {
  /* <тут switch (operator), и т.д.> */
  schm.forEach(item => {
    /* <тут какая-то работа с method и condition item'ов> */
    if (item.operator)   // или if (item.item)
      processScheme(item); 
  }); 
}


Оффтоп:
Если свойство-массив item у элементов первого уровня схемы всегда присутствует (независимо от значения operator), то логичнее вынести перебор этого свойства за пределы if или case - для DRY и повышения читаемости кода.

То есть,

  • действия при разных значениях operator оформить функциями (для удобства можно засунуть их в объект, где ключами являются значения operator)
  • в кейсах switch (operator) помещать ссылку на нужную функцию в переменную, скажем func. А если сделано объектом, то необходимость в ветвлении вовсе отпадает:
    func = opFunctions[schm.operator];
  • далее из переменнной и вызывать, типа
    func(item.method, item.condition);

Еще можно map'ить массив item в массив результатов, затем передавая его аргументом в функцию оператора... так не придется хранить промежуточные результаты. Ведь в любом случае проверяются все элементы item (и по-моему, это неоптимально), так как работу forEach нельзя прервать кроме как исключением.

Методы (обработку элементов condition) желательно так же оформить отдельными функциями. В общем, тут само собой напрашивается объектное решение: это позволит держать всю логику в одном месте (в объекте и его методах), при этом не создавая единую "монстр-функцию" парсинга, или целый ворох хелперов (все это будет сложно поддерживать, а объектную реализацию - легко. К тому же, решение на объектах и прототипах это "JS-way").

READ ALSO
как изменить строку в объекте через setState? [закрыт]

как изменить строку в объекте через setState? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос, чтобы он соответствовал тематике «Stack Overflow на русском»

183
Не работает слайдер в js/jquery

Не работает слайдер в js/jquery

У меня есть две функции, которые показывают / скрывают элементы за счет манипуляции классами и css переходами:

130
Как реализовать прозрачность вокруг указателя?

Как реализовать прозрачность вокруг указателя?

Коллеги подскажите на JS(или на чистом css возможно) при помощи чего можно реализовать подобное решение https://wwwkikk

147