Est-il mauvais de vérifier si un tableau est non vide en utilisant la méthode any?
?
a = [1,2,3]
a.any?
=> true
a.clear
a.any?
=> false
Ou est-il préférable d'utiliser unless a.empty?
?
any?
n'est pas identique à 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? retournera true si au moins un des membres de la collection n'est pas false ou nil).
La méthode empty?
provient de la classe Array
http://Ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F
Il sert à vérifier si le tableau contient quelque chose ou non. Cela inclut les choses qui sont considérées comme fausses, telles que zéro et faux.
>> 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 "toutes" les valeurs du tableau sont évaluées à true. Des méthodes similaires à ceci ne sont aucune? tout? et une? où ils vérifient tous combien de fois vrai 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
Si vous préfixez l'instruction avec un point d'exclamation, vous saurez si le tableau n'est pas vide. Donc dans votre cas -
a = [1,2,3]
!a.empty?
=> true
Evitez any?
pour les tableaux de grande taille.
any?
est O(n)
empty?
est O(1)
any?
ne vérifie pas la longueur, mais analyse en réalité tout le tableau pour rechercher des éléments véridiques.
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?
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 "clairsemés" qui commencent par beaucoup de valeurs nil
, comme par exemple un tableau qui vient d'être créé.
Je suggérerai d'utiliser unless
et blank
pour vérifier si elle est vide ou non.
Exemple :
unless a.blank?
a = "Is not empty"
end
Cela saura "un" vide ou pas. Si 'a' est vide, le code ci-dessous ne fonctionnera pas.
Je ne pense pas que ce soit mauvais d'utiliser any?
du tout. Je l'utilise beaucoup. C'est clair et concis.
Cependant, si toutes les valeurs de nil
vous préoccupent, alors vous demandez si le tableau contient size > 0
. Dans ce cas, cette extension simple morte (PAS optimisée, à la manière de 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
Ceci 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 à considérer:
present?
de ActiveSupport.String
, qui ignore les espaces (comme present?
.).length?
pour String
ou d'autres types où il pourrait être plus descriptif.Integer
et d’autres types Numeric
, de sorte qu’un zéro logique renvoie false
.