Как оценить массив логических значений и логических операторов - PullRequest
0 голосов
/ 11 мая 2018

У меня есть массив логических значений true или false, разделенных строками, которые выражают логический оператор || или &&, например:

[true, "||", false, "&&", true]

Размер массива не фиксирован. Я хочу оценить первые три элемента [true, "||", false] и оценить результат, а также оставшуюся часть массива.

Я думаю об использовании:

array.each_slice(3).to_a.reduce

Но я не уверен, что нужно передать в блоке reduce. Здесь нужно какое-то направление.

1 Ответ

0 голосов
/ 11 мая 2018

Код

def evaluate(arr)
  pairs = arr.drop(1).each_slice(2)
  pairs.reduce(arr.first) { |rv, (op, bool)| op == '&&' ? rv && bool : rv || bool }
end

Примеры

evaluate [true, '&&', false, '||', true]   #=> true
evaluate [false, '||', true, '&&', false]  #=> false

Пояснение

Предположим

arr = [true, '&&', false, '||', true]

Затем

a = arr.drop(1)         #=> ["&&", false, "||", true]
pairs = a.each_slice(2) #=> #<Enumerator: ["&&", false, "||", true]:each_slice(2)>

Мы можем видеть, какие элементы перечислитель pairs отправит в блок, преобразовав его в массив.

pairs.to_a              #=> [["&&", false], ["||", true]]

Продолжение(rv является коротким для возвращаемого значения ), мы генерируем первый элемент pairs, передаем его в блок и присваиваем значения переменным блока op и bool.

rv = arr.first          #=> true
op, bool = pairs.next   #=> ["&&", false]
op                      #=> "&&"
bool                    #=> false

Теперь выполним расчет блока.Поскольку

op == '&&'              #=> true

блок вычисляет и возвращает следующее, которое является новым значением памятки , rv:

rv && bool              #=> true && false => false

Теперь мы генерируемвторой и последний элемент pairs, передайте его в блок, присвойте значения переменным блока (вспомните, что rv теперь равно false) и выполните вычисление блока.

op, bool = pairs.next   #=> ["||", true]
op                      #=> "||"
bool                    #=> true

op == '&&'              #=> false
rv || bool              #=> false || true #=> true

Таким образом, методвозвращает true.

Использование Kernel # eval вместо

Если мы доверяем значениям в массиве, мы могли бы просто написать

eval [true, '&&', false, '||', true].join  #=> true
eval [false, '||', true, '&&', false].join #=> false

Использование eval позволило бы нам добавить "(", ")" and "!" `В массив, что значительно увеличило диапазон логических выражений, которые можно было бы оценить (легко).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...