Verifique se o array não está vazio: algum?

191

É ruim verificar se uma matriz não está vazia usando o any?método?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Ou é melhor usar unless a.empty??

sivabudh
fonte

Respostas:

248

any?não é o mesmo que not empty?em alguns casos.

>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false

A partir da documentação:

Se o bloco não for fornecido, Ruby adiciona um bloco implícito de {| obj | obj} (qualquer um? retornará true se pelo menos um dos membros da coleção não for falso ou nulo).

Marcel Jackwerth
fonte
8
Existe alguma função oposta a empty??
RocketR
12
@RocketR, você pode querer fazer o checkout present?.
dantheta 3/12/12
15
@dantastic #present?é apenas para Rails. Em puro Ruby você terá NoMethodError: undefined method 'present?' for Array.
RocketR
6
Não exatamente exatamente Rails, o Suporte Ativo pode ser usado sem trilhos, basta require 'activesupport'.
Sergio A.
83

A diferença entre uma matriz que avalia seus valores para trueou se está vazia.

O método empty?vem da classe Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

É usado para verificar se a matriz contém algo ou não. Isso inclui coisas que avaliam false, como nile false.

>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false

O método any?vem do módulo Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

É usado para avaliar se "qualquer" valor na matriz é avaliado true. Métodos semelhantes a este são none?, all?e one?, onde tudo apenas verificar para ver quantas vezes verdadeira poderia ser avaliada. que não tem nada a ver com a contagem de valores encontrados em uma matriz.

caso 1

>> a = []
=> []
>> a.any?
=> false
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> true

caso 2

>> a = [nil, true]
=> [nil, true]
>> a.any?
=> true
>> a.one?
=> true
>> a.all?
=> false
>> a.none?
=> false

caso 3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false
Empurrador de polígono
fonte
31

O prefixo da instrução com um ponto de exclamação permitirá que você saiba se a matriz não está vazia. Então, no seu caso -

a = [1,2,3]
!a.empty?
=> true
Denny Abraham Cheriyan
fonte
27
Negação dupla? Você está falando sério?
3lvis
29
Ele não é tão sério!
Alexander Ave
5
Ele Ele. A negação dupla não é ideal, apenas parece mais legível neste caso específico.
Denny Abraham Cheriyan 13/03/16
12
O negativo duplo fazia parte da pergunta original "Verifique se a matriz não está vazia". Isso responde à pergunta.
mattfitzgerald
30

Evite any?para matrizes grandes.

  • any? é O(n)
  • empty? é O(1)

any? não verifica o comprimento, mas verifica na verdade toda a matriz em busca de elementos verdadeiros.

static VALUE
rb_ary_any_p(VALUE ary)
{
  long i, len = RARRAY_LEN(ary);
  const VALUE *ptr = RARRAY_CONST_PTR(ary);

  if (!len) return Qfalse;
  if (!rb_block_given_p()) {
    for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
  }
  else {
    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
    }
  }
  return Qfalse;
}

empty? por outro lado, verifica apenas o comprimento da matriz.

static VALUE
rb_ary_empty_p(VALUE ary)
{
  if (RARRAY_LEN(ary) == 0)
    return Qtrue;
  return Qfalse;
}

A diferença é relevante se você tiver matrizes "esparsas" que começam com muitos nilvalores, como, por exemplo, uma matriz que acabou de ser criada.

akuhn
fonte
Nesse caso de uso, a diferença é relevante apenas se você tiver matrizes "esparsas" que começam com muitos nilvalores, com matrizes "normais" any?sem retorno de bloco no primeiro elemento, portanto a complexidade ainda é O (1) como o empty?método
David Costa
4

Vou sugerir o uso unlesse blankpara verificar se está vazio ou não.

Exemplo:

unless a.blank?
  a = "Is not empty"
end

Isso saberá 'a' vazio ou não. Se 'a' estiver em branco, o código abaixo não será executado.

Dennis
fonte
4
#blank?faz parte do Rails. Se eles já estão usando o Rails, #present?é a negação de #blank?qualquer maneira.
Eva
0

Eu não acho que é ruim de usar any?. Eu uso isto muito. É claro e conciso.

No entanto, se você está preocupado com todos os nilvalores que estão jogando fora, está realmente perguntando se a matriz possui size > 0. Nesse caso, essa extensão simples (NÃO otimizada, no estilo de macaco) o aproximaria.

Object.class_eval do

  def size?
    respond_to?(:size) && size > 0
  end

end

> "foo".size?
 => true
> "".size?
 => false
> " ".size?
 => true
> [].size?
 => false
> [11,22].size?
 => true
> [nil].size?
 => true

Isso é bastante descritivo, perguntando logicamente "esse objeto tem um tamanho?". E é conciso e não requer o ActiveSupport. E é fácil de construir.

Alguns extras a serem considerados:

  1. Isso não é o mesmo present?do ActiveSupport.
  2. Você pode querer uma versão personalizada para String, que ignore o espaço em branco (como present?faz).
  3. Você pode querer o nome length?para Stringou outros tipos em que possa ser mais descritivo.
  4. Você pode querer personalizá-lo para Integere outros Numerictipos, para que um zero lógico retorne false.
lilole
fonte