Почему все? return true в пустом массиве?
Использование Ruby Я хочу оценить все элементы в массиве и вернуть true, если все они проходят условный тест.
Я могу сделать это, используя, например, array.all? { |value| value == 2 }
Итак:
> array=[2,2]
> array.all? { |value| value == 2 }
=> true
> array=[2,3]
> array.all? { |value| value == 2 }
=> false
Отлично!
Но почему пустой тест проходит этот тест?
> array=[]
> array.all? { |value| value == 2 }
=> true
Если это не возвращает false?
И если мне нужно, чтобы он возвращал false, как мне изменить метод?
Ответы
Ответ 1
В Ruby вы никогда не сможете перебрать пустую коллекцию (массив, хэши и т.д.), поэтому в вашем случае ваш блок никогда не будет выполнен. И если блок никогда не будет выполнен, all?
возвращает true (нет условия, чтобы сделать результат ложным).
Прочитайте all?
в документацию Ruby.
Вы можете просто достичь своей цели
!array.empty? && array.all? { |value| value == 2 }
Ответ 2
Это пустота правды. Это стандартная интерпретация универсальной квантификации, т.е. A
collection.all? { |x| some_predicate(x) }
над пустым collection
, но он, как известно, поражает людей как интуитивно понятные, когда они впервые видят его в формальной настройке. Один хороший способ подумать о том, почему это предпочтительная семантика, - подумать о том, как реализовать all?
.
Чтобы сделать ваш тест, требуется, чтобы массив был непустым, просто выполните
array.any? && array.all? { |x| x == 2 }
Обратите внимание, что array.any?
выполняется быстро, независимо от того, насколько велик массив, тогда как array.all? { |x| x == 2 }
может быть медленным, в зависимости от того, насколько велика array
и насколько редка 2
в ней. Поэтому сначала поставьте array.any?
.
Также обратите внимание, что существуют вырожденные случаи, когда это не будет работать, например, если array
есть [nil]
или [false]
. Если такие ситуации могут возникнуть, замените array.any?
на array.any? { true }
.
Ответ 3
В документации говорится: "Метод возвращает true, если блок никогда не возвращает false или noil".
В случае пустого массива блок никогда не выполняется и, следовательно, метод всегда будет возвращать true
. Что касается возврата false
, вам придется arr.empty?
Ответ 4
В этом массиве нет элемента, который не проходит тест. Я думаю, вам может потребоваться выполнить проверку длины массива.
Ответ 5
Просто пойдите
!(array.empty? || array.any? {|x| x != 2})
(у которого есть дополнительное преимущество неудачной работы, то есть его можно корректно оценивать, не проверяя весь массив.)
Ответ 6
Так как в массиве нет элемента, который НЕИСПРАВНОСТЬ тестирует, он возвращает true. Поэтому просто используйте somehting, например:
array.size > 0 and array.all? { |value| value == 2}
Или что-то в этом роде.
Ответ 7
Нули, пустые коллекции, пустые матрицы и т.д. всегда были немного особенными, если не откровенно проблематичными. Греки хорошо знали, почему они не посчитали 0 среди натуральных целых чисел.
Метод all?
будет первым, кто спросит вас: "Почему вы звоните мне на пустой массив?" Что вы подразумеваете под "всем?", Когда там ничего нет? Это противоречие. И метод делает короткое размышление и отвечает true
по причинам, изложенным в других трех ответах. Помните, что вы ошибаетесь, говоря о "всех элементах" пустого массива для начала.
Ответ 8
Как пишет Амит Кумар Гупта, это стандартная интерпретация универсальной квантификации. Я понятия не имею, почему вы ожидаете, что это будет false
. Здесь вы можете видеть, что это должно быть true
путем вывода.
Универсальное квантификация эквивалентно объединению, поэтому ( "< = > " означает эквивалент):
"for all x in [a, b, c], P(x)" <=> "P(a) and P(b) and P(c)"
Обратите внимание, что любое предложение эквивалентно объединению истины и самого себя, поэтому:
"for all x in [a, b, c], P(x)" <=> "true and P(a) and P(b) and P(c)"
Если вы уменьшите элементы в наборе до двух, вы получите:
"for all x in [a, b], P(x)" <=> "true and P(a) and P(b)"
и далее к одному элементу:
"for all x in [a], P(x)" <=> "true and P(a)"
Теперь, что происходит с пустым множеством? Естественно,
"for all x in [], P(x)" <=> "true"
Заметив, что экзистенциальная квантификация эквивалентна дизъюнкции, вы также можете увидеть, что вы должны ожидать false
с экзистенциальной квантификацией над пустым множеством.
Ответ 9
Источник всего? метод говорит, что он использует статическую переменную (которая первоначально установлена в true), а затем выполняет операцию И между статическим значением переменной и результатом итерации в конечном итоге возвращает эту статическую переменную.
поскольку массив пуст, Ruby никогда не будет итерации в этом пустом массиве и в результате этого все? метод вернет статическую переменную, для которой установлено значение true.
Ответ 10
Убедитесь, что массив сначала не пуст.
Тогда:
array.compact.present? && array.all? {|x| x != 2}