2010-07-20 9 views
6

Je souhaite utiliser la fonction pack() en Perl pour coder certaines données. Ensuite, je veux comparer ma structure emballée à une autre structure emballée. Je veux que cette comparaison soit sur les valeurs de byte de cette structure empaquetée.Comment comparer les valeurs compressées en Perl?

Selon la documentation, cmp utilise l'environnement local actuel pour déterminer comment comparer les chaînes. Mais je ne veux pas d'intelligence appliquée à la comparaison. Je veux ce qui est le plus proche d'un memcmp(). Évidemment, je ne peux pas utiliser <=> pour comparer mes objets emballés car ils ne sont pas des nombres.

Quelle est la meilleure façon de comparer les chaînes compressées en Perl?

Sidenote: J'ai lu this article on efficient sorting in Perl qui note que la fonction de tri simple utilise un algorithme de type memcmp pour comparer les structures. Je me demande comment réaliser une telle comparaison sans avoir à utiliser le tri.

+1

'sort' est vraiment un excellent endroit pour commencer. Essayer de construire votre propre système de tri ne fonctionnera probablement pas aussi bien que vous le voudriez, car le tri Perl a été réglé avec précision au fil des années. Le lien de tri efficace que vous avez donné inclut en fait des instructions sur l'utilisation de structures de données compactes pour accélérer le tri, ce qui est assez intelligent, mais le tri prendrait beaucoup de temps avant que je me consacre à maintenir cela. – sarnold

+0

Voulez-vous une comparaison (c'est-à-dire, inférieure, supérieure ou égale à) ou un test d'égalité oui ou non? –

+0

@gbacon: Je veux quelque chose avec lequel je peux commander, donc moins que, plus grand que, égal à. –

Répondre

5

considérations locale Désactiver pour le bloc et utiliser cmp comme d'habitude:

sub mycmp { 
    no locale; 
    $_[0] cmp $_[1]; 
} 

La documentation perlop fournit

lt, le, ge, gt et cmp utiliser le tri (collation) spécifié par l'environnement local actuel si use locale est actif. Voir perllocale.

puis en perllocale

Le comportement par défaut est restaurée avec le no locale pragma, ou après avoir atteint la fin du bloc englobant use locale.

Par exemple, en cours d'exécution

my($one,$two) = map pack("N", $_) => 1, 2; 
say mycmp($one, $two); 
say mycmp($two, $one); 

sorties

-1 
1
+0

Est-ce que "aucun paramètre régional" ne s'applique qu'à la fermeture? S'il y a une localisation qui s'applique en dehors de la fermeture, cela s'appliquera-t-il toujours à tout code situé en dessous de la fermeture? –

+0

@PP Oui, le pragma 'locale' est lexical: il est en effet seulement dans son bloc englobant. –

0

Réflexion à haute voix ici - les opérateurs bit à bit aideront-ils? Comme faire un XOR sur deux chaînes identiques donnera un bitstring avec tout réglé sur 0.

http://perldoc.perl.org/perlop.html#Bitwise-String-Operators

+0

xor serait un bon test d'égalité indépendant des paramètres régionaux, en fait - bonne idée - ne serait pas utile pour moins de/plus grand que par contre. –

4

Expand, then contract. Comparer par exemple la représentation hexagonale de vos structures, qui utilise uniquement des caractères ASCII et ne peuvent susciter des conflits les paramètres régionaux problème que vous mentionnez.

unpack('H*', $first) cmp unpack('H*', $second) 
Questions connexes