2013-07-29 3 views
0

J'ai ce code, et j'obtenir l'avertissement: Argument "" isn't numeric in numeric eq (==) pour $id == $_Argument « » est pas numérique dans l'équation numérique (==)

@delete a des numéros provenant d'un formulaire web (demande de CGI), et c'est probablement la raison pour laquelle perl traite ces nombres comme des chaînes. Cela fonctionne bien, mais je ne sais pas quoi faire à propos des avertissements.

my @IDs = (21, 36, 6, 7, 64, 6435, 24); 
for my $id (@IDs) { 
    push @insert, $id if (grep $id == $_, @delete) 
} 

Je ne veux pas les avertissements. Quelle est ma meilleure option?

J'ai d'abord pensé à l'itération sur la matrice et en appelant int pour chaque élément, mais je n'ai pas aimé l'idée.

Répondre

2

... c'est pourquoi perl traite ces nombres comme des chaînes

Non, Perl convertit vos données en nombre à cause de l'opérateur d'égalité numérique ==. Quand il avertit à propos de "", cela signifie que vous avez une chaîne vide, et il sera converti en zéro 0. En d'autres termes, votre tableau @delete contient un élément vide.

Ce que vous devriez probablement faire est d'utiliser à la place un hachage:

my @IDs = (21, 36, 6, 7, 64, 6435, 24); 
my %ID = map { $_ => 1 } @IDs; 
my @insert = grep $ID{$_}, @delete; 

Cela évitera toute conversion, qui peut être à la fois une bonne chose et une mauvaise. D'une part, il ne convertira pas la chaîne vide à zéro, mais il ne convertira pas non plus la chaîne " 12" au numéro 12.

Votre problème avec les chaînes vides restera, mais tant que vous n'avez pas de clé pour la chaîne vide, tout ira bien.

En outre, vous devriez garder à l'esprit pourquoi ils sont appelés "avertissements". Ils sont là pour indiquer que vous faites quelque chose qui ne va pas. Donc, faire taire les avertissements sans savoir pourquoi est une très mauvaise chose. Dans ce cas, vous devez déterminer précisément ce que vous voulez faire avec des valeurs de chaîne vides. (Et d'autres mauvaises valeurs possibles).

Vous pouvez supprimer les valeurs de chaîne vides de votre tableau en faisant ceci:

@delete = grep !/^$/, @delete; 
+0

Quelle est la meilleure méthode? '@delete = grep!/^ $ /, @delete;' Ou '@delete = grep! $ _, @delete;' Bonne explication. Effacé beaucoup de doutes. – GrSrv

+1

Merci. Eh bien, '!/^ $ /' Et '! $ _' Font l'opposé l'un de l'autre dans ce cas. La chaîne vide est une valeur fausse, donc la nier la rend vraie.Cependant, faire un vrai/faux est également dangereux, car il peut créer des faux négatifs (si zéro '0' est une valeur valide), et des faux positifs (par exemple des lettres ou des espaces). Si vous obtenez vos valeurs à partir d'un formulaire Web, vous devez probablement les vérifier en premier. Dans ce cas, le premier est plus sûr, car il ne fait qu'une chose: vérifier si la chaîne est vide. – TLP

3

Si 0 est pas une carte d'identité valide, utilisez un syntaxt comme grep ceci:

grep { $_ and ($id == $_) } @delete; 

ou, un match si $ _ a seulement des chiffres:

grep { /\d+/ and ($id == $_) } @delete; 
2

Démo rapide de votre problème:

use strict; 
use warnings; 

my @insert; 
my @IDs = (21, 36, 6, 7, 64, 6435, 24); 

my @delete = split//, "1 2 4"; 
warn "this is ok"; 
for my $id (@IDs) { push @insert, $id if (grep { $id == $_ } @delete) } 

warn "now get warning"; 
@delete = split//, "1 2 4"; 
#      ^^ note two spaces - the split will produce one empty element 
for my $id (@IDs) { push @insert, $id if (grep { $id == $_ } @delete) } 

Vous devez valider votre entrée uniquement pour les numéros.