2009-08-10 32 views
8

dado algo como¿Perl garantiza devolución de claves hash ordenadas?

foreach (keys %myHash) { 
    ... do stuff ... 
} 

foreach (keys %myHash) { 
    ... do more stuff ... 
} 

Es Perl garantizado para iterar sobre las claves en un orden consistente si el hash no se altera?

+0

Sólo por curiosidad, ¿para qué necesita esta propiedad? – hillu

+1

¿Quién votando por cualquier cosa? – erjiang

Respuesta

26

Yes. De perldoc -f keys:

Las claves se devuelven en un orden aparentemente aleatorio. El orden aleatorio real está sujeto a cambios en versiones futuras de perl, pero se garantiza que es el mismo orden que la función values o each (dado que el hash no se ha modificado). Desde Perl 5.8.1 el orden es diferente incluso entre diferentes ejecuciones de Perl por razones de seguridad (ver "Ataques de complejidad algorítmica" en perldoc perlsec).

(el énfasis es mío)

+12

+1 Sería genial si la gente al menos intentara leer la excelente documentación que viene con Perl. –

-2

Ésta es una expectativa bastante arriesgado. Probablemente lo hará, pero ¿por qué preocuparse? Obtenga las claves por adelantado, guarde el resultado y repita el resultado guardado. Entonces, tiene la garantía de acceder a las claves en el mismo orden. Trabajar alrededor de los bordes de los detalles de implementación no especificados es peligroso.

EDITAR: Perdí la "garantía" en el documento, pero todavía creo que es peligroso esperar que esto nunca cambie. Especialmente cuando hay formas más sanas de lograr los mismos fines.

+2

¿Por qué las cotizaciones de susto de "garantía"?Está (a) muy claramente establecido; (b) es poco probable que cambie, porque es importante que 'claves' y 'valores' vuelvan en el mismo orden, de modo que los dos puedan correlacionarse para cuando no se pueda usar 'cada'. – derobert

0

Editar:

Aunque un hash normal tiene un orden coherente, en el caso de un tied hash el orden de las claves es no está bien definido, ya que es controlado por el usuario!


Aunque el orden de la tecla hash no cambia, es probable que deba reconsiderar por qué necesita hacer esto.

¿Quizás pueda procesar el hash en una sola pasada en lugar de en dos?

Debe guardar las claves hash en una matriz como una práctica de programación defensiva, a menos que el tamaño de los datos sea lo suficientemente grande como para duplicarlo sería un problema. Como beneficio adicional, incluso puede ordenar la lista fácilmente y procesar en el hash en un orden bien definido. Por ejemplo,

my @keys = sort keys %myHash; 

Esto evita cualquier problema con la modificación del hachís, ya que su pedido gama nunca va a cambiar a menos que lo desee.

Si no hace esto, debe tener mucho cuidado de no hacer nada que cambie el hash, de lo contrario el orden de los elementos cambiará. Mire en el módulo Readonly para asegurarse de que este hash nunca se modifique.

+0

No lo entiendo, ¿por qué debería estar a la defensiva acerca de una función que ha sido probada, documentada y garantizada para funcionar? Esto parece tan tonto como usar un editor de texto y llamar a Archivo -> Seguro dos veces seguidas con la esperanza de que si el primero falla silenciosamente, el segundo tendrá éxito. – moritz

+2

@moritz: El problema no es que Perl cambie el orden de las teclas (o no), sino que la orden puede cambiar si se modifica el hash. Esta respuesta sugiere una táctica de programación defensiva (matriz separada más Readonly) para el mantenimiento futuro de la base de código de OP, y no tiene nada que ver con las partes internas de Perl. –

+3

A menos que haya fuertes razones de rendimiento para no hacerlo, trato de ordenar siempre. Ha sido mordido demasiado a menudo por un código que implícitamente espera un cierto orden y comienza a fallar misteriosamente cuando los cambios aparentemente no relacionados dan como resultado un orden de claves diferente. – ysth

Cuestiones relacionadas