Vérifiez que le tableau n'est pas vide: un?

191

Est-il mauvais de vérifier si un tableau n'est pas vide en utilisant la any?méthode?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Ou vaut-il mieux l'utiliser unless a.empty??

sivabudh
la source

Réponses:

248

any?n'est pas la même que not empty?dans certains cas.

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

De la documentation:

Si le bloc n'est pas donné, Ruby ajoute un bloc implicite de {| obj | obj} (c'est-à-dire any? retournera true si au moins un des membres de la collection n'est pas faux ou nul).

Marcel Jackwerth
la source
8
Y a-t-il une fonction opposée à empty??
RocketR
12
@RocketR, vous voudrez peut-être vérifier la present?méthode.
dantheta
15
@dantastic #present?est uniquement Rails. En pur Ruby, vous obtiendrez NoMethodError: undefined method 'present?' for Array.
RocketR
6
Pas exactement uniquement Rails, Active Support peut être utilisé sans rails, il suffit de le faire require 'activesupport'.
Sergio A.
83

La différence entre un tableau évaluant ses valeurs trueou s'il est vide.

La méthode empty?provient de la classe Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Il est utilisé pour vérifier si le tableau contient quelque chose ou non. Cela inclut les éléments qui évaluent false, tels que nilet false.

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

La méthode any?provient du module Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Il est utilisé pour évaluer si "une" valeur du tableau est évaluée à true. Des méthodes similaires à celle-ci sont none?, all?et one?, où elles vérifient toutes simplement combien de fois true pourrait être évalué. ce qui n'a rien à voir avec le nombre de valeurs trouvées dans un tableau.

cas 1

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

cas 2

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

cas 3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false
Poussoir de polygone
la source
31

Le préfixe de l'instruction avec un point d'exclamation vous permettra de savoir si le tableau n'est pas vide. Donc dans votre cas -

a = [1,2,3]
!a.empty?
=> true
Denny Abraham Cheriyan
la source
27
Double négation? Es-tu sérieux?
3lvis
29
Il n'est donc pas sérieux!
Alexander Bird
5
Hehe. La double négation n'est pas idéale, semble juste plus lisible dans ce cas précis.
Denny Abraham Cheriyan
12
Le double négatif faisait partie de la question initiale "Vérifier que le tableau n'est pas vide". Cela répond à la question.
mattfitzgerald
30

Évitez les any?grands tableaux.

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

any? ne vérifie pas la longueur mais scanne en fait l'ensemble du tableau pour les éléments de vérité.

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? d'autre part vérifie uniquement la longueur du tableau.

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

La différence est pertinente si vous avez des tableaux "épars" qui commencent par beaucoup de nilvaleurs, comme par exemple un tableau qui vient d'être créé.

Akuhn
la source
Dans ce cas d'utilisation, la différence n'est pertinente que si vous avez des tableaux "épars" qui commencent par beaucoup de nilvaleurs, avec des tableaux "normaux" any?sans retour de bloc au premier élément, donc la complexité est toujours O (1) comme la empty?méthode
David Costa
4

Je vous suggère d'utiliser unlesset blankde vérifier est vide ou non.

Exemple :

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

Cela saura «un» vide ou non. Si «a» est vide, le code ci-dessous ne fonctionnera pas.

Dennis
la source
4
#blank?fait partie de Rails. S'ils utilisent déjà Rails, #present?c'est la négation de #blank?toute façon.
Eva
0

Je ne pense pas que ce soit mauvais à utiliser any?du tout. Je l'utilise beaucoup. C'est clair et concis.

Cependant, si vous êtes préoccupé par toutes les nilvaleurs qui le jettent, vous demandez vraiment si le tableau a size > 0. Dans ce cas, cette extension simple morte (PAS optimisée, style singe) vous rapprocherait.

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

C'est assez descriptif, demandant logiquement "cet objet a-t-il une taille?". Et c'est concis, et cela ne nécessite pas ActiveSupport. Et c'est facile à construire.

Quelques extras auxquels réfléchir:

  1. Ce n'est pas la même chose que present?depuis ActiveSupport.
  2. Vous voudrez peut-être une version personnalisée pour String, qui ignore les espaces (comme le present?fait).
  3. Vous voudrez peut-être le nom length?pour Stringou d'autres types où il pourrait être plus descriptif.
  4. Vous voudrez peut-être qu'il soit personnalisé pour Integeret d'autres Numerictypes, de sorte qu'un zéro logique retourne false.
lilole
la source