Esta comparación de lenguajes de programación (matrices asociativas) compara las características de las estructuras de datos de matrices asociativas o el procesamiento de búsqueda de matrices para más de 40 lenguajes de programación informática .
La siguiente es una comparación de matrices asociativas (también "mapeo", "hash" y "diccionario") en varios lenguajes de programación.
AWK tiene soporte integrado a nivel de lenguaje para matrices asociativas.
Por ejemplo:
directorio telefónico [ "Sally Smart" ] = "555-9999" directorio telefónico [ "John Doe" ] = "555-1212" directorio telefónico [ "J. Random Hacker" ] = "555-1337"
El siguiente código recorre una matriz asociada e imprime su contenido:
para ( nombre en la agenda telefónica ) { imprimir nombre , " " , agenda telefónica [ nombre ] }
El usuario puede buscar elementos en una matriz asociativa y eliminar elementos de la matriz.
A continuación se muestra cómo se pueden simular matrices asociativas multidimensionales en AWK estándar utilizando la concatenación y la variable separadora de cadenas incorporada SUBSEP:
{ # para cada línea de entrada multi [ $ 1 SUBSEP $ 2 ] ++ ; } # FIN { for ( x in multi ) { split ( x , arr , SUBSEP ); print arr [ 1 ], arr [ 2 ], multi [ x ]; } }
No existe una implementación estándar de matrices asociativas en C , pero está disponible una biblioteca de terceros, C Hash Table, con licencia BSD. [1]
Otra biblioteca de terceros, uthash, también crea matrices asociativas a partir de estructuras C. Una estructura representa un valor y uno de los campos de la estructura sirve como clave. [2]
Por último, la biblioteca GLib también admite matrices asociativas, junto con muchos otros tipos de datos avanzados y es la implementación recomendada del Proyecto GNU. [3]
De manera similar a GLib , el marco multiplataforma Core Foundation de Apple ofrece varios tipos de datos básicos. En particular, existen CFDictionary y CFMutableDictionary con recuento de referencias.
C# utiliza las clases de colección proporcionadas por .NET Framework . El tipo de matriz asociativa más utilizado es System.Collections.Generic.Dictionary<TKey, TValue>
, que se implementa como una tabla hash mutable. El System.Collections.Immutable
paquete relativamente nuevo, disponible en las versiones 4.5 y posteriores de .NET Framework y en todas las versiones de .NET Core , también incluye el System.Collections.Immutable.Dictionary<TKey, TValue>
tipo , que se implementa mediante un árbol AVL . Los métodos que normalmente mutarían el objeto en el lugar devuelven en cambio un nuevo objeto que representa el estado del objeto original después de la mutación.
A continuación se muestran tres formas de completar un diccionario mutable:
Add
método que agrega una clave y un valor y lanza una excepción si la clave ya existe en el diccionario;var dictionary = new Dictionary < string , string > (); dictionary . Add ( "Sally Smart" , "555-9999" ); dictionary [ "John Doe" ] = "555-1212" ; // No permitido en C#. // dictionary.Item("J. Random Hacker") = "553-1337"; dictionary [ "J. Random Hacker" ] = "553-1337" ;
El diccionario también se puede inicializar durante la construcción utilizando un "inicializador de colección", que compila llamadas repetidas a Add
.
var diccionario = nuevo Diccionario < cadena , cadena > { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" } };
Los valores se recuperan principalmente utilizando el indexador (que genera una excepción si la clave no existe) y el TryGetValue
método, que tiene un parámetro de salida para el valor buscado y un valor de retorno booleano que indica si se encontró la clave.
var sallyNumber = diccionario [ "Sally Smart" ];
var sallyNumber = ( diccionario.TryGetValue ( " Sally Smart" , salida var resultado ) ? resultado : "n/a " ;
En este ejemplo, el sallyNumber
valor ahora contendrá la cadena "555-9999"
.
Un diccionario puede verse como una secuencia de claves, una secuencia de valores o una secuencia de pares de claves y valores representados por instancias del KeyValuePair<TKey, TValue>
tipo, aunque no hay garantía de orden. Para un diccionario ordenado, el programador podría optar por utilizar un SortedDictionary<TKey, TValue>
o utilizar el método de extensión .Sort
LINQ al enumerar.
A continuación se muestra la enumeración utilizando un bucle foreach :
// recorrer la colección y mostrar cada entrada. foreach ( KeyValuePair < string , string > kvp in dictionary ) { Console.WriteLine ( " El número de teléfono de {0} es {1}" , kvp.Key , kvp.Value ) ; }
C++ tiene una forma de matriz asociativa llamada std::map
(consulte la Biblioteca de plantillas estándar#Contenedores ). Se podría crear un mapa de la guía telefónica con el siguiente código en C++:
#include <mapa> #include <cadena> #include <utilidad> int main () { std :: map < std :: string , std :: string > libreta_telefonica ; libreta_telefonica.insert ( std :: make_pair ( "Sally Smart" , "555-9999" )); libreta_telefonica.insert ( std :: make_pair ( " John Doe" , "555-1212" )); libreta_telefonica.insert ( std :: make_pair ( " J. Random Hacker" , " 553-1337 " ) ); }
O de manera menos eficiente, ya que esto crea std::string
valores temporales:
#include <mapa> #include <cadena> int main () { std :: map < std :: string , std :: string > libreta_telefonica ; libreta_telefonica [ "Sally Smart" ] = "555-9999" ; libreta_telefonica [ "John Doe" ] = "555-1212" ; libreta_telefonica [ "J. Random Hacker" ] = "553-1337" ; }
Con la extensión de las listas de inicialización en C++11, se pueden agregar entradas durante la construcción de un mapa como se muestra a continuación:
#include <mapa> #include <cadena> int main () { std :: map < std :: string , std :: string > libreta_telefonica { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Hacker aleatorio" , "553-1337" } }; }
Puede iterar a través de la lista con el siguiente código (C++03):
std :: map < std :: string , std :: string > :: iterador curr , fin ; para ( curr = phone_book.begin ( ) , fin = phone_book.end (); curr ! = fin ; ++ curr ) std :: cout << curr - > primero << " = " << curr -> segundo << std :: endl ;
La misma tarea en C++11:
para ( const auto & curr : libreta_telefonica ) std :: cout << curr .first << " = " << curr .second << std :: endl ;
Usando el enlace estructurado disponible en C++17 :
para ( const auto & [ nombre , número ] : agenda_telefonica ) { std :: cout << nombre << " = " << número << std :: endl ; }
En C++, la std::map
clase se basa en plantillas, lo que permite que los tipos de datos de las claves y los valores sean diferentes para las distintas map
instancias. Para una instancia determinada de la map
clase, las claves deben ser del mismo tipo base. Lo mismo debe ser cierto para todos los valores. Aunque std::map
normalmente se implementa utilizando un árbol binario de búsqueda autoequilibrado , C++11 define un segundo mapa llamado std::unordered_map
, que tiene las características algorítmicas de una tabla hash. Esta es también una extensión de proveedor común para la Biblioteca de plantillas estándarhash_map
(STL), normalmente llamada , disponible en implementaciones como SGI y STLPort.
Inicializando un diccionario vacío y agregando elementos en Cobra :
dic como Diccionario < de Cadena , Cadena > = Diccionario < de Cadena , Cadena > () dic.add ( 'Sally Smart' , ' 555-9999' ) dic.add ( ' John Doe' , ' 555-1212' ) dic.add ( ' J. Random Hacker' , '553-1337 ' ) afirmar dic [ 'Sally Smart' ] == '555-9999'
Alternativamente, un diccionario se puede inicializar con todos los elementos durante la construcción:
dic = { 'Sally Smart' : '555-9999' , 'John Doe' : '555-1212' , 'J. Hacker aleatorio' : '553-1337' }
El diccionario se puede enumerar mediante un bucle for, pero no hay un orden garantizado:
para clave , val en dic imprime "el número de teléfono de [clave] es [val]"
Una estructura en ColdFusion Markup Language (CFML) es equivalente a una matriz asociativa:
dynamicKeyName = "John Doe" ; phoneBook = { "Sally Smart" = "555-9999" , " #dynamicKeyName# " = "555-4321" , "J. Random Hacker" = "555-1337" , UnknownComic = "???" }; writeOutput ( phoneBook.UnknownComic ); // ??? writeDump ( phoneBook ); // estructura completa
D ofrece soporte directo para matrices asociativas en el lenguaje principal; dichas matrices se implementan como una tabla hash encadenada con árboles binarios. [4] El ejemplo equivalente sería:
int main () { string [ string ] libreta_telefonica ; libreta_telefonica [ "Sally Smart" ] = "555-9999" ; libreta_telefonica [ "John Doe" ] = "555-1212" ; libreta_telefonica [ "J. Random Hacker" ] = "553-1337" ; devolver 0 ; }
Las claves y los valores pueden ser de cualquier tipo, pero todas las claves de una matriz asociativa deben ser del mismo tipo y lo mismo se aplica a los valores dependientes.
Recorrer todas las propiedades y valores asociados e imprimirlos se puede codificar de la siguiente manera:
foreach ( clave , valor ; libreta telefónica ) { writeln ( "Número para " ~ clave ~ ": " ~ valor ); }
Una propiedad se puede eliminar de la siguiente manera:
libreta_telefonica .remove ( "Sally Smart" ) ;
Delphi admite varios contenedores estándar, incluido TDictionary<T>:
utiliza SysUtils , Generics , Colecciones ; var PhoneBook : TDictionary < cadena , cadena >; Entrada : TPair < cadena , cadena >; comenzar PhoneBook := TDictionary < string , string >. Crear ; PhoneBook . Añadir ( 'Sally Smart' , '555-9999' ) ; PhoneBook . Añadir ( 'John Doe' , '555-1212' ) ; PhoneBook . Añadir ( 'J. Random Hacker' , '553-1337' ) ; para la entrada en la libreta telefónica, haga Writeln ( Formato ( 'Número para %s: %s' , [ Entrada . Clave , Entrada . Valor ])) ; fin .
Las versiones de Delphi anteriores a 2009 no admiten matrices asociativas directamente. Dichas matrices se pueden simular utilizando la clase TStrings:
procedimiento TForm1 . Button1Click ( Sender : TObject ) ; var DataField : TStrings ; i : Integer ; begin DataField := TStringList . Create ; Campo de datos . Valores [ 'Sally Smart' ] := '555-9999' ; Campo de datos . Valores [ 'John Doe' ] := '555-1212' ; Campo de datos . Valores [ 'J. Random Hacker' ] := '553-1337' ; // acceder a una entrada y mostrarla en un cuadro de mensaje ShowMessage ( DataField . Values [ 'Sally Smart' ]) ; // recorrer la matriz asociativa para i := 0 hasta DataField . Count - 1 do begin ShowMessage ( 'Número para ' + DataField . Names [ i ] + ': ' + DataField . ValueFromIndex [ i ]) ; end ; Campo de datos . Libre ; fin ;
Erlang ofrece muchas formas de representar asignaciones; tres de las más comunes en la biblioteca estándar son listas de claves, diccionarios y mapas.
Las listas de claves son listas de tuplas , donde el primer elemento de cada tupla es una clave y el segundo es un valor. En el lists
módulo se proporcionan funciones para operar con listas de claves.
Libreta telefónica = [{ "Sally Smith" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" }].
El acceso a un elemento de la lista de claves se puede realizar con la lists:keyfind/3
función:
{_, Teléfono } = listas : keyfind ( "Sally Smith" , 1 , Libreta telefónica ), io : formato ( "Número de teléfono: ~s~n " , [ Teléfono ]).
Los diccionarios se implementan en el dict
módulo de la biblioteca estándar. Se crea un nuevo diccionario mediante la dict:new/0
función y se almacenan nuevos pares clave/valor mediante la dict:store/3
función:
PhoneBook1 = dict : new (), PhoneBook2 = dict : store ( "Sally Smith" , "555-9999" , Dict1 ), PhoneBook3 = dict : store ( "John Doe" , "555-1212" , Dict2 ), PhoneBook = dict : store ( "J. Random Hacker" , "553-1337" , Dict3 ).
Una inicialización en serie de este tipo se representaría de forma más idiomática en Erlang con la función adecuada:
Libreta telefónica = dict : from_list ([{ "Sally Smith" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" }]).
Se puede acceder al diccionario mediante la dict:find/2
función:
{ ok , Teléfono } = dict : find ( "Sally Smith" , Libreta telefónica ), io : format ( "Teléfono: ~s~n " , [ Teléfono ]).
En ambos casos, se puede utilizar cualquier término de Erlang como clave. Las variaciones incluyen el orddict
módulo, que implementa diccionarios ordenados, y el módulo gb_trees
, que implementa árboles balanceados generales.
Los mapas se introdujeron en OTP 17.0, [5] y combinan las ventajas de las listas de claves y los diccionarios. Un mapa se define utilizando la sintaxis #{ K1 => V1, ... Kn => Vn }
:
Libreta telefónica = #{ "Sally Smith" => "555-9999" , "John Doe" => "555-1212" , "J. Random Hacker" => "553-1337" }.
El módulo dispone de funciones básicas para interactuar con los mapas maps
. Por ejemplo, la maps:find/2
función devuelve el valor asociado a una clave:
{ ok , Teléfono } = mapas : find ( "Sally Smith" , Libreta telefónica ), io : format ( "Teléfono: ~s~n " , [ Teléfono ]).
A diferencia de los diccionarios, los mapas pueden coincidir con patrones según:
#{ "Sally Smith" , Teléfono } = Libreta telefónica , io : formato ( "Teléfono: ~s~n " , [ Teléfono ]).
Erlang también proporciona sintaxis para actualizaciones funcionales: crea un nuevo mapa basado en uno existente, pero con valores modificados o claves adicionales:
PhoneBook2 = PhoneBook #{ % el operador `:=` actualiza el valor asociado con una clave existente "J. Random Hacker" : = "355-7331" , % el operador `=>` agrega un nuevo par clave-valor, potencialmente reemplazando uno existente "Alice Wonderland" => "555-1865" }
En tiempo de ejecución, F# proporciona el Collections.Map<'Key,'Value>
tipo, que es un árbol AVL inmutable .
El siguiente ejemplo llama al Map
constructor, que opera sobre una lista (una secuencia de elementos delimitada por punto y coma encerrada entre corchetes) de tuplas (que en F# son secuencias de elementos delimitadas por comas).
deje que los números = [ "Sally Smart" , "555-9999" ; "John Doe" , "555-1212" ; "J. Random Hacker" , "555-1337" ] |> Mapa
Los valores se pueden buscar a través de uno de los Map
miembros, como su indexador o Item
propiedad (que genera una excepción si la clave no existe) o la TryFind
función, que devuelve un tipo de opción con un valor de Some <result>
, para una búsqueda exitosa, o None
, para una búsqueda fallida. Luego se puede utilizar la coincidencia de patrones para extraer el valor sin procesar del resultado, o se puede establecer un valor predeterminado.
deje que sallyNumber = números .[ "Sally Smart" ] // o deje que sallyNumber = números . Item ( "Sally Smart" )
sea sallyNumber = match numbers . TryFind ( "Sally Smart" ) con | Some ( number ) -> number | None -> "n/a"
En ambos ejemplos anteriores, el sallyNumber
valor contendría la cadena "555-9999"
.
Debido a que F# es un lenguaje .NET, también tiene acceso a las características de .NET Framework , incluido el tipo (que se implementa como una tabla hash ), que es el tipo de matriz asociativa principal que se usa en C# y Visual Basic. Este tipo puede ser el preferido al escribir código que está destinado a funcionar con otros lenguajes en .NET Framework, o cuando se prefieren las características de rendimiento de una tabla hash sobre las de un árbol AVL.System.Collections.Generic.Dictionary<'TKey,'TValue>
La dict
función proporciona un medio para crear de manera conveniente un diccionario .NET que no está destinado a ser mutado; acepta una secuencia de tuplas y devuelve un objeto inmutable que implementa IDictionary<'TKey,'TValue>
.
deje que los números sean [ "Sally Smart" , "555-9999" ; "John Doe" , "555-1212" ; "J. Random Hacker" , "555-1337" ] |> dict
Cuando se necesita un diccionario mutable, se puede llamar directamente al constructor de . Consulte el ejemplo de C# en esta página para obtener información adicional.System.Collections.Generic.Dictionary<'TKey,'TValue>
let números = Sistema . Colecciones . Genérico . Diccionario < cadena , cadena > () números . Agregar ( "Sally Smart" , "555-9999" ) números .[ "John Doe" ] <- "555-1212" números . Elemento ( "J. Hacker aleatorio" ) <- "555-1337"
IDictionary
Las instancias tienen un indexador que se utiliza de la misma manera que Map
, aunque el equivalente a TryFind
es TryGetValue
, que tiene un parámetro de salida para el valor buscado y un valor de retorno booleano que indica si se encontró la clave.
deje que sallyNumber = deje que mutable result = "" si números . TryGetValue ( "Sally Smart" , & result ) entonces result de lo contrario "n/a"
F# también permite llamar a la función como si no tuviera ningún parámetro de salida y en su lugar devolviera una tupla que contiene su valor de retorno regular y el valor asignado al parámetro de salida:
deje que sallyNumber = match numbers . TryGetValue ( "Sally Smart" ) con | true , number -> number | _ -> "n/a"
Un diccionario o mapa se puede enumerar utilizando Seq.map
.
// recorrer la colección y mostrar cada entrada. números |> Seq . map ( fun kvp -> printfn "El número de teléfono de %O es %O" kvp . Key kvp . Value )
Visual FoxPro implementa la asignación con la clase de colección.
mapping = NEWOBJECT ( "Collection" ) mapping.Add ( "Narcisos" , "flor2" ) && Add(objeto, clave) – la clave debe ser un carácter index = mapping.GetKey ( "flor2" ) && devuelve el valor del índice 1 object = mapping( "flor2" ) && devuelve "Narcisos" (obtener por clave) object = mapping(1) && devuelve "Narcisos" (obtener por índice)
GetKey devuelve 0 si no se encuentra la clave.
Go tiene soporte integrado a nivel de lenguaje para matrices asociativas, llamadas "mapas". El tipo de clave de un mapa solo puede ser un tipo booleano, numérico, de cadena, de matriz, de estructura, de puntero, de interfaz o de canal.
Un tipo de mapa se escribe:map[keytype]valuetype
Agregar elementos uno a uno:
agenda_telefonica := make ( map [ string ] string ) // crea un mapa vacío agenda_telefonica [ "Sally Smart" ] = "555-9999" agenda_telefonica [ "John Doe" ] = "555-1212" agenda_telefonica [ "J. Random Hacker" ] = "553-1337"
Un mapa literal:
libreta_telefonica := mapa [ cadena ] cadena { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "553-1337" , }
Iterando a través de un mapa:
// sobre las claves y los valores para clave, valor:= rango phone_book { fmt.Printf ( " Número para % s : % s \ n" , clave , valor ) } // sobre solo claves para clave := rango agenda telefónica { fmt . Printf ( "Nombre: %s\n" , clave ) }
El lenguaje de programación Haskell proporciona solo un tipo de contenedor asociativo: una lista de pares:
m = [( "Sally Smart" , "555-9999" ), ( "John Doe" , "555-1212" ), ( "J. Hacker aleatorio" , "553-1337" )] principal = imprimir ( buscar "John Doe" m )
producción:
Sólo "555-1212"
Tenga en cuenta que la función de búsqueda devuelve un valor "Tal vez", que es "Nada" si no se encuentra, o "Solo 'resultado ' " cuando se encuentra.
El compilador Glasgow Haskell (GHC), la implementación de Haskell más utilizada, ofrece dos tipos más de contenedores asociativos. Otras implementaciones también pueden ofrecerlos.
Uno de ellos son los mapas funcionales polimórficos (representados como árboles binarios equilibrados inmutables):
importar Data.Map calificado como M m = M . insertar "Sally Smart" "555-9999" M . vacío m' = M . insertar "John Doe" "555-1212" m m'' = M . insertar "J. Random Hacker" "553-1337" m' principal = imprimir ( M . buscar "John Doe" m'' :: Tal vez String )
producción:
Sólo "555-1212"
También existe una versión especializada para claves enteras llamada Data.IntMap.
Finalmente, una tabla hash polimórfica:
Importar datos calificados.HashTable como H principal = do m <- H . nuevo ( == ) H . cadena hash H . insertar m "Sally Smart" "555-9999" H . insertar m "John Doe" "555-1212" H . insertar m "J. Hacker aleatorio" "553-1337" foo <- H . búsqueda m "John Doe" imprimir foo
producción:
Sólo "555-1212"
Tanto las listas de pares como los mapas funcionales proporcionan una interfaz puramente funcional, que es más idiomática en Haskell. Por el contrario, las tablas hash proporcionan una interfaz imperativa en la mónada IO .
En Java, las matrices asociativas se implementan como "mapas", que forman parte del marco de colecciones de Java . Desde J2SE 5.0 y la introducción de genéricos en Java, las colecciones pueden tener un tipo especificado; por ejemplo, una matriz asociativa que asigna cadenas a cadenas podría especificarse de la siguiente manera:
Mapa < String , String > phoneBook = new HashMap < String , String > (); phoneBook . put ( "Sally Smart" , "555-9999" ); phoneBook . put ( "John Doe" , "555-1212" ); phoneBook . put ( "J. Random Hacker" , "555-1337" );
El get
método se utiliza para acceder a una clave; por ejemplo, el valor de la expresión phoneBook.get("Sally Smart")
es "555-9999"
. Este código utiliza un mapa hash para almacenar la matriz asociativa, llamando al constructor de la HashMap
clase. Sin embargo, dado que el código solo utiliza métodos comunes a la interfaz Map
, se podría utilizar un árbol binario autoequilibrado llamando al constructor de la TreeMap
clase (que implementa la subinterfaz SortedMap
), sin cambiar la definición de la phoneBook
variable, ni el resto del código, ni utilizar otras estructuras de datos subyacentes que implementen la Map
interfaz.
La función hash en Java, utilizada por HashMap y HashSet, la proporciona el Object.hashCode()
método . Dado que cada clase en Java hereda de Object
, cada objeto tiene una función hash. Una clase puede anular la implementación predeterminada de hashCode()
para proporcionar una función hash personalizada más acorde con las propiedades del objeto.
La Object
clase también contiene el equals(Object)
método que prueba la igualdad de un objeto con otro objeto. Las estructuras de datos con hash en Java se basan en que los objetos mantengan el siguiente contrato entre sus métodos hashCode()
y equals()
:
Para dos objetos a y b ,
a . igual a ( b ) == b . igual a ( a ) si a . igual a ( b ), entonces a . hashCode () == b . hashCode ()
Para mantener este contrato, una clase que anula equals()
también debe anular hashCode()
, y viceversa, de modo que hashCode()
se base en las mismas propiedades (o un subconjunto de las propiedades) que equals()
.
Otro contrato que una estructura de datos hash tiene con el objeto es que los resultados de los métodos hashCode()
y equals()
no cambiarán una vez que el objeto se haya insertado en el mapa. Por este motivo, generalmente es una buena práctica basar la función hash en propiedades inmutables del objeto.
De manera análoga, TreeMap y otras estructuras de datos ordenados requieren que se defina un ordenamiento en el tipo de datos. O bien el tipo de datos ya debe haber definido su propio ordenamiento, mediante la implementación de la Comparable
interfaz; o bien se debe proporcionar uno personalizado Comparator
en el momento en que se construye el mapa. Al igual que con HashMap mencionado anteriormente, el ordenamiento relativo de las claves en un TreeMap no debe cambiar una vez que se hayan insertado en el mapa.
JavaScript (y su versión estandarizada, ECMAScript ) es un lenguaje orientado a objetos basado en prototipos .
El JavaScript moderno maneja matrices asociativas, utilizando las clases Map
y WeakMap
. Un mapa no contiene ninguna clave de forma predeterminada; solo contiene lo que se le introduce explícitamente. Las claves y los valores pueden ser de cualquier tipo (incluidas funciones, objetos o cualquier primitivo).
Se puede inicializar un mapa con todos los elementos durante la construcción:
const phoneBook = new Mapa ([ [ "Sally Smart" , "555-9999" ], [ "John Doe" , "555-1212" ], [ "J. Random Hacker" , "553-1337" ], ]);
Alternativamente, puede inicializar un mapa vacío y luego agregar elementos:
const phoneBook = new Map (); phoneBook . set ( "Sally Smart" , "555-9999" ); phoneBook . set ( "John Doe" , "555-1212" ); phoneBook . set ( "J. Random Hacker" , "553-1337" );
El acceso a un elemento del mapa se puede realizar con el get
método:
const sallyNumber = phoneBook . get ( "Sally Smart" );
En este ejemplo, el valor sallyNumber
ahora contendrá la cadena "555-9999".
Las claves de un mapa están ordenadas. Por lo tanto, al iterarlo, un objeto de mapa devuelve las claves en el orden de inserción. A continuación, se muestra la enumeración mediante un bucle for:
// recorrer la colección y mostrar cada entrada. for ( const [ name , number ] of phoneBook ) { console . log ( `El número de teléfono para ${ name } es ${ number } ` ); }
Una llave se puede quitar de la siguiente manera:
agenda telefónica .delete ( "Sally Smart" ) ;
Un objeto es similar a un mapa: ambos permiten establecer claves en valores, recuperar esos valores, eliminar claves y detectar si un valor está almacenado en una clave. Por este motivo (y porque no había alternativas integradas), históricamente los objetos se han utilizado como mapas.
Sin embargo, existen diferencias importantes que hacen que un mapa sea preferible en ciertos casos. En JavaScript, un objeto es una asignación de nombres de propiedades a valores, es decir, una matriz asociativa con una salvedad: las claves de un objeto deben ser una cadena o un símbolo (se permiten objetos nativos y primitivos convertidos implícitamente a claves de cadena). Los objetos también incluyen una característica no relacionada con las matrices asociativas: un objeto tiene un prototipo, por lo que contiene claves predeterminadas que podrían entrar en conflicto con claves definidas por el usuario. Por lo tanto, realizar una búsqueda de una propiedad apuntará la búsqueda a la definición del prototipo si el objeto no define la propiedad.
Un objeto literal se escribe como { property1: value1, property2: value2, ... }
. Por ejemplo:
const myObject = { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Hacker aleatorio" : "553-1337" , };
Para evitar que la búsqueda utilice las propiedades del prototipo, puede utilizar la Object.setPrototypeOf
función:
Objeto .setPrototypeOf ( myObject , null ) ;
A partir de ECMAScript 5 (ES5), el prototipo también se puede omitir mediante Object.create(null)
:
const myObject = Object . create ( null ); Objeto . asignar ( miObjeto , { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "553-1337" , });
Si el nombre de la propiedad es un identificador válido, se pueden omitir las comillas, por ejemplo:
const miOtroObjeto = { foo : 42 , bar : falso };
La búsqueda se escribe utilizando notación de acceso a propiedades, ya sea corchetes, que siempre funcionan, o notación de puntos, que solo funciona para claves de identificador:
miObjeto [ "John Doe" ] miOtroObjeto . foo
También puede recorrer todas las propiedades enumerables y los valores asociados de la siguiente manera (un bucle for-in):
para ( const propiedad en myObject ) { const valor = myObject [ propiedad ]; console . log ( `myObject[ ${ propiedad } ] = ${ valor } ` ); }
O (un bucle for-of):
para ( const [ propiedad , valor ] de Object . entradas ( myObject )) { console . log ( ` ${ propiedad } = ${ valor } ` ); }
Una propiedad se puede eliminar de la siguiente manera:
eliminar miObjeto [ "Sally Smart" ];
Como se mencionó anteriormente, las propiedades son cadenas y símbolos. Dado que cada objeto nativo y primitivo se puede convertir implícitamente en una cadena, puede hacer lo siguiente:
myObject [ 1 ] // la clave es "1"; tenga en cuenta que myObject[1] == myObject["1"] myObject [[ "a" , "b" ]] // la clave es "a,b" myObject [{ toString () { return "hola mundo" ; } }] // la clave es "hola mundo"
En el JavaScript moderno, se considera de mala educación utilizar el tipo Array como una matriz asociativa. Existe consenso en que el tipo Object y las clases Map
/ WeakMap
son las mejores para este propósito. El razonamiento detrás de esto es que si Array se extiende a través de prototipos y Object se mantiene prístino, los bucles for y for-in funcionarán como se espera en "matrices" asociativas. Este problema ha salido a la luz debido a la popularidad de los marcos de JavaScript que hacen un uso intensivo y, a veces, indiscriminado de prototipos para extender los tipos incorporados de JavaScript.
Consulte el Día de concientización sobre prototipos de objetos y matrices de JavaScript para obtener más información sobre el tema.
En Julia , las siguientes operaciones gestionan matrices asociativas.
Declarar diccionario:
directorio telefónico = Dict ( "Sally Smart" => "555-9999" , "John Doe" => "555-1212" , "J. Random Hacker" => "555-1337" )
Elemento de acceso:
directorio telefónico [ "Sally Smart" ]
Añadir elemento:
directorio telefónico [ "Nuevo contacto" ] = "555-2222"
Eliminar elemento:
¡Borrar! ( guía telefónica , "Sally Smart" )
Obtener claves y valores como iterables :
claves ( agenda telefónica ) valores ( agenda telefónica )
En KornShell 93 y shells compatibles (ksh93, bash4...), se pueden utilizar las siguientes operaciones con matrices asociativas.
Definición:
typeset -A agenda telefónica ; # ksh93; en bash4+, "typeset" es un sinónimo del más preferido "declare", que funciona de forma idéntica en este caso agenda telefónica =([ "Sally Smart" ]= "555-9999" [ "John Doe" ]= "555-1212" [ "[[J. Random Hacker]]" ]= "555-1337" ) ;
Desreferenciar:
${ agenda telefónica [ "John Doe" ] } ;
Lisp fue concebido originalmente como un lenguaje de "procesamiento de listas", y uno de sus tipos de datos más importantes es la lista enlazada, que puede tratarse como una lista de asociación ("alist").
' (( "Sally Smart" . "555-9999" ) ( "John Doe" . "555-1212" ) ( "J. Random Hacker" . "553-1337" ))
La sintaxis (x . y)
se utiliza para indicar un par de cons
matrices asociativas . Las claves y los valores no necesitan ser del mismo tipo dentro de una lista. Lisp y Scheme proporcionan operadores como este assoc
para manipular listas de forma similar a las matrices asociativas.
Existe un conjunto de operaciones específicas para el manejo de listas de asociaciones para Common Lisp , y cada una de ellas funciona de forma no destructiva.
Para agregar una entrada acons
se utiliza la función que crea y devuelve una nueva lista de asociación. Una lista de asociación en Common Lisp imita una pila, es decir, se adhiere al principio de último en entrar, primero en salir (LIFO) y, por lo tanto, se antepone al encabezado de la lista.
( let (( directorio telefónico NIL )) ( setf directorio telefónico ( acons "Sally Smart" "555-9999" directorio telefónico )) ( setf directorio telefónico ( acons "John Doe" "555-1212" directorio telefónico )) ( setf directorio telefónico ( acons "J. Random Hacker" "555-1337" directorio telefónico )))
Esta función puede interpretarse como una adaptación a cons
las operaciones. [6]
;; El efecto de ;; (cons (cons CLAVE VALOR) ALIST) ;; es equivalente a ;; (acons CLAVE VALOR ALIST) ( let (( phone-book ' (( "Sally Smart" . "555-9999" ) ( "John Doe" . "555-1212" )))) ( cons ( cons "J. Random Hacker" "555-1337" ) phone-book ))
Por supuesto, la operación destructiva push
también permite insertar entradas en una lista de asociación, debiendo cada entrada constituir una clave-valor cons para conservar la validez del mapeo.
( push ( cons "Dummy" "123-4567" ) guía telefónica )
La búsqueda de una entrada por su clave se realiza mediante assoc
, que puede configurarse para el predicado de prueba y la dirección, especialmente la búsqueda en la lista de asociaciones desde el final hasta el principio. El resultado, si es positivo, devuelve la entrada completa cons, no solo su valor. Si no se obtiene una clave coincidente, se devuelve el NIL
valor.
( directorio telefónico de la asociación "John Doe" : prueba #' cadena= )
Dos generalizaciones de assoc
exist: assoc-if
espera una función de predicado que prueba la clave de cada entrada, devolviendo la primera entrada para la cual el predicado produce un NIL
valor distinto al invocarse. assoc-if-not
invierte la lógica, aceptando los mismos argumentos, pero devolviendo la primera entrada que genera NIL
.
;; Encuentra la primera entrada cuya clave sea igual a "John Doe". ( assoc-if #' ( lambda ( key ) ( string= key "John Doe" )) phone-book ) ;; Encuentra la primera entrada cuya clave no sea ni "Sally Smart" ni "John Doe" ( assoc-if-not #' ( lambda ( key ) ( member key ' ( "Sally Smart" "John Doe" ) :test #' string= )) phone-book )
El proceso inverso, la detección de una entrada por su valor, utiliza rassoc
.
;; Buscamos la primera entrada con un valor de "555-9999". ;; Probamos los valores de la cadena de entrada con el predicado "string=". ( rassoc "555-9999" phone-book :test #' string= )
Las generalizaciones correspondientes rassoc-if
existen rassoc-if-not
.
;; Encuentra la primera entrada cuyo valor sea "555-9999". ( rassoc-if #' ( lambda ( valor ) ( string= valor "555-9999" )) agenda-telefonica ) ;; Encuentra la primera entrada cuyo valor no sea "555-9999". ( rassoc-if-not #' ( lambda ( value ) ( string= value "555-9999" )) phone-book )
Todas las funciones de búsqueda de entradas anteriores se pueden reemplazar por variantes generales centradas en listas, como find
, find-if
, find-if-not
, así como funciones pertinentes como position
y sus derivados.
;; Busque una entrada con la clave "John Doe" y el valor "555-1212". ( find ( cons "John Doe" "555-1212" ) phone-book :test #' equal )
La eliminación, a falta de un equivalente específico, se basa en las facilidades de la lista, incluidas las destructivas.
;; Crea y devuelve una lista al sin ninguna entrada cuya clave sea igual a "John Doe". ( remove-if #' ( lambda ( entry ) ( string= ( car entry ) "John Doe" )) phone-book )
La iteración se realiza con la ayuda de cualquier función que espere una lista.
;; Iterar a través de "mapa". ( mapa NIL #' ( lambda ( entrada ) ( destructuring-bind ( clave . valor ) entrada ( formato T "~&~s => ~s" clave valor ))) libreta-telefonica ) ;; Iterar a través de "dolist". ( dolist ( entrada libreta-telefonica ) ( destructuring-bind ( clave . valor ) entrada ( formato T "~&~s => ~s" clave valor )))
Al ser listas estructuradas, se pueden aplicar operaciones de procesamiento y transformación sin restricciones.
;; Devuelve un vector de los valores de la "libreta telefónica". ( map 'vector #' cdr libreta telefónica ) ;; Modificar destructivamente la "guía telefónica" mediante "map-into". ( map-into guía telefónica #' ( lambda ( entrada ) ( destructuring-bind ( clave . valor ) entrada ( cons ( reverse clave ) ( reverse valor )))) guía telefónica )
Debido a su naturaleza lineal, las listas de asociaciones se utilizan para conjuntos de datos relativamente pequeños. Common Lisp también admite un tipo de datos de tabla hash y, para Scheme, se implementan en SRFI 69. Las tablas hash tienen una mayor sobrecarga que las listas de asociaciones, pero proporcionan un acceso mucho más rápido cuando hay muchos elementos. Otra característica es el hecho de que las tablas hash de Common Lisp no mantienen, a diferencia de las listas de asociaciones, el orden de inserción de las entradas.
Las tablas hash de Common Lisp se construyen mediante la make-hash-table
función , cuyos argumentos incluyen, entre otras configuraciones, un predicado para probar la clave de entrada. Si bien se toleran objetos arbitrarios, incluso la heterogeneidad dentro de una única instancia de tabla hash, la especificación de esta :test
función clave se limita a entidades distinguibles: el estándar Common Lisp solo exige el soporte de eq
, eql
, equal
y equalp
, pero designa operaciones adicionales o personalizadas como permisibles para implementaciones concretas.
( let (( directorio-telefónico ( make-hash-table :test #' equal ))) ( setf ( gethash directorio-telefónico "Sally Smart" ) "555-9999" ) ( setf ( gethash directorio-telefónico "John Doe" ) "555-1212" ) ( setf ( gethash directorio-telefónico "J. Random Hacker" ) "553-1337" ))
La gethash
función permite obtener el valor asociado a una clave.
( guía telefónica de "John Doe" de gethash )
Además, se puede especificar un valor predeterminado para el caso de una tecla ausente.
( gethash "Incógnito" directorio telefónico 'no existe tal clave )
Una invocación de gethash
en realidad devuelve dos valores: el valor o valor sustituto de la clave y un indicador booleano, que retorna T
si la tabla hash contiene la clave y NIL
para señalar su ausencia.
( enlace-de-valor-múltiple ( valor contiene-clave ) ( gethash libreta telefónica "Sally Smart" ) ( si contiene-clave ( formato T "~& El valor asociado es: ~s" valor ) ( formato T "~& No se pudo encontrar la clave." )))
Se utiliza remhash
para eliminar la entrada asociada a una clave.
( remhash de la guía telefónica de "J. Random Hacker" )
clrhash
vacía completamente la tabla hash.
( clrhash directorio telefónico )
La maphash
función dedicada se especializa en iterar tablas hash.
( maphash #' ( lambda ( clave valor ) ( formato T "~&~s => ~s" clave valor )) libreta telefónica )
Alternativamente, el loop
constructo prevé iteraciones, a través de claves, valores o conjunciones de ambos.
;; Itera las claves y valores de la tabla hash. ( bucle para clave que es la clave hash de la guía telefónica usando ( valor -hash valor ) hacer ( formato T "~&~s => ~s" clave valor )) ;; Itera los valores de la tabla hash. ( bucle para valor siendo los valores hash de la libreta telefónica do ( imprimir valor ))
Una opción adicional invoca with-hash-table-iterator
, una macro creadora de iteradores, cuyo procesamiento debe ser controlado por el llamador.
( con iterador de tabla hash ( generador de entradas directorio telefónico ) ( bucle do ( enlace de valores múltiples ( tiene entrada clave valor ) ( generador de entradas ) ( si tiene entrada ( formato T "~&~s => ~s" clave valor ) ( fin de bucle )))))
Es fácil construir tipos de datos abstractos compuestos en Lisp, utilizando estructuras o características de programación orientada a objetos, junto con listas, matrices y tablas hash.
LPC implementa matrices asociativas como un tipo fundamental conocido como "mapa" o "mapeo", según el controlador. Las claves y los valores pueden ser de cualquier tipo. Un literal de mapeo se escribe como ([ key_1 : value_1, key_2 : value_2 ])
. El código de procedimiento se ve así:
asignación de libreta_telefonica = ([]); libreta_telefonica [ "Sally Smart" ] = "555-9999" ; libreta_telefonica [ "John Doe" ] = "555-1212" ; libreta_telefonica [ "J. Random Hacker" ] = "555-1337" ;
Se accede a las asignaciones para leer usando el operador de indexación de la misma manera que para escribir, como se muestra arriba. Por lo tanto, phone_book["Sally Smart"] devolvería la cadena "555-9999", y phone_book["John Smith"] devolvería 0. La prueba de presencia se realiza usando la función member(), por ejemploif(member(phone_book, "John Smith")) write("John Smith is listed.\n");
La eliminación se realiza mediante una función llamada m_delete() o map_delete(), según el controlador:m_delete(phone_book, "Sally Smart");
Los controladores LPC de la familia Amylaar implementan asignaciones multivalor utilizando un índice numérico secundario (otros controladores de la familia MudOS no admiten asignaciones multivalor). Sintaxis de ejemplo:
asignación de libreta_telefonica = ([ : 2 ]); libreta_telefonica [ "Sally Smart" , 0 ] = "555-9999" ; libreta_telefonica [ "Sally Smart" , 1 ] = "99 Sharp Way" ; libreta_telefonica [ "John Doe" , 0 ] = "555-1212" ; libreta_telefonica [ "John Doe" , 1 ] = "3 Nigma Drive" ; libreta_telefonica [ "J. Random Hacker" , 0 ] = "555-1337" ; libreta_telefonica [ "J. Random Hacker" , 1 ] = "77 Massachusetts Avenue" ;
Los controladores LPC lo suficientemente modernos como para soportar una construcción foreach() lo utilizan para iterar a través de sus tipos de mapeo.
En Lua , "tabla" es un tipo fundamental que puede utilizarse como una matriz (índice numérico, rápido) o como una matriz asociativa.
Las claves y los valores pueden ser de cualquier tipo, excepto nulo. A continuación, nos centraremos en los índices no numéricos.
Una literal de tabla se escribe como { value, key = value, [index] = value, ["non id string"] = value }
. Por ejemplo:
phone_book = { [ "Sally Smart" ] = "555-9999" , [ "John Doe" ] = "555-1212" , [ "J. Random Hacker" ] = "553-1337" , -- Se permite una coma al final }aTable = { -- Tabla como valor subTable = { 5 , 7.5 , k = true }, -- la clave es "subTable" -- Función como valor [ 'John Doe' ] = función ( edad ) si edad < 18 entonces devuelve "Joven" de lo contrario devuelve "¡Viejo!" fin fin , -- La tabla y la función (y otros tipos) también se pueden usar como claves }
Si la clave es un identificador válido (no una palabra reservada), se pueden omitir las comillas. Los identificadores distinguen entre mayúsculas y minúsculas.
La búsqueda se escribe utilizando corchetes, que siempre funcionan, o notación de puntos, que solo funciona para claves de identificador:
imprimir ( aTable [ "John Doe" ]( 45 )) x = aTable . subTable . k
También puedes recorrer todas las claves y valores asociados con iteradores o bucles for:
simple = { [ true ] = 1 , [ false ] = 0 , [ 3.14 ] = math.pi , x = 'x' , [ "!" ] = 42 } function FormatElement ( clave , valor ) return "[" .. tostring ( clave ) .. "] = " .. valor .. ", " end -- Itera sobre todas las claves table . foreach ( simple , function ( k , v ) io.write ( FormatElement ( k , v )) end ) print "" para k , v en pares ( simple ) do io.write ( FormatElement ( k , v )) end print "" k = nulo repeat k , v = next ( simple , k ) if k ~= nulo then io.write ( FormatElement ( k , v )) end Until k == nulo print ""
Se puede eliminar una entrada configurándola como nula:
simple . x = nulo
Asimismo, puedes sobrescribir valores o agregarlos:
simple [ '%' ] = "porcentaje" simple [ '!' ] = 111
Mathematica y Wolfram Language utilizan la expresión Asociación para representar matrices asociativas. [7]
directorio telefónico = <| "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" |> ;
Para acceder: [8]
directorio telefónico [[ Tecla [ "Sally Smart" ]]]
Si las claves son cadenas, la palabra clave Key no es necesaria, por lo que:
directorio telefónico [[ "Sally Smart" ]]
Para listar las claves: [9] y los valores [10]
Llaves[guía telefónica]Valores[guía telefónica]
En MUMPS, cada matriz es una matriz asociativa. El soporte directo integrado a nivel de lenguaje para matrices asociativas se aplica a matrices privadas específicas de procesos almacenadas en memoria, denominadas "locales", así como a matrices globales permanentes y compartidas almacenadas en disco que están disponibles simultáneamente para varios trabajos. El nombre de las matrices globales está precedido por el acento circunflejo "^" para distinguirlas de las variables locales.
SET ^phonebook("Sally Smart")="555-9999" ;; almacenando datos permanentesSET phonebook("John Doe")="555-1212" ;; almacenando datos temporalesSET phonebook("J. Random Hacker")="553-1337" ;; almacenando datos temporalesMERGE ^phonebook=phonebook ;; copiando datos temporales en datos permanentes
Para acceder al valor de un elemento simplemente es necesario utilizar el nombre con el subíndice:
ESCRIBE "Número de teléfono :",^phonebook("Sally Smart"),!
También puedes recorrer una matriz asociada de la siguiente manera:
ESTABLECER NOMBRE=""PARA S NOMBRE=$ORDEN(^phonebook(NOMBRE)) SALIR:NOMBRE="" ESCRIBIR NOMBRE," Número de teléfono :",^phonebook(NOMBRE),!
Cocoa y GNUstep , escritos en Objective-C , manejan matrices asociativas usando NSMutableDictionary
(una versión mutable de NSDictionary
) la clase cluster. Esta clase permite asignaciones entre dos objetos cualesquiera. Se hace una copia del objeto clave antes de insertarlo en NSMutableDictionary
, por lo tanto, las claves deben cumplir con el NSCopying
protocolo. Cuando se inserta en un diccionario, el objeto de valor recibe un mensaje de retención para aumentar su recuento de referencias. El objeto de valor recibirá el mensaje de liberación cuando se elimine del diccionario (ya sea explícitamente o agregando al diccionario un objeto diferente con la misma clave).
NSMutableDictionary * aDictionary = [[ NSMutableDictionary alloc ] init ]; [ aDictionary setObject : @"555-9999" paraClave : @"Sally Smart" ]; [ aDictionary setObject : @"555-1212" paraClave : @"John Doe" ]; [ aDictionary setObject : @"553-1337" paraClave : @"Hacker aleatorio" ];
Para acceder a los objetos asignados, se puede utilizar este comando:
id anObject = [ unDiccionario objetoParaClave : @"Sally Smart" ];
Todas las claves o valores se pueden enumerar utilizando NSEnumerator
:
NSEnumerator * keyEnumerator = [ aDictionary keyEnumerator ]; id key ; while (( key = [ keyEnumerator nextObject ])) { // ... procesarlo aquí ... }
En Mac OS X 10.5+ y iPhone OS, las claves del diccionario se pueden enumerar de forma más concisa utilizando la NSFastEnumeration
construcción: [11]
para ( id clave en un Diccionario ) { // ... procesarlo aquí ... }
Lo que es aún más práctico es que se pueden crear fácilmente gráficos de datos estructurados utilizando Cocoa , especialmente NSDictionary
( NSMutableDictionary
). Esto se puede ilustrar con este ejemplo compacto:
NSDictionary * aDictionary = [ NSDictionary diccionarioConObjetosYClaves : [ NSDictionary diccionarioConObjetosYClaves : @"555-9999" , @"Sally Smart" , @"555-1212" , @"John Doe" , nil ], @"estudiantes" , [ NSDictionary diccionarioConObjetosYClaves : @"553-1337" , @"Hacker Aleatorio" , nil ], @"hackers" , nil ];
Se puede acceder rápidamente a los campos relevantes mediante rutas clave:
id unObjeto = [ unDiccionario valorParaRutaClave : @"estudiantes.Sally Smart" ];
El lenguaje de programación OCaml ofrece tres contenedores asociativos diferentes. El más simple es una lista de pares:
# let m = [ "Sally Smart" , "555-9999" ; "Juan Pérez" , "555-1212" ; "J. Hacker aleatorio" , "553-1337" ];; val m : ( cadena * cadena ) lista = [ ( "Sally Smart" , "555-9999" ); ( "Juan Pérez" , "555-1212" ); ( "J. Hacker aleatorio" , "553-1337" ) ] # Lista . assoc "Juan Pérez" m ;; - : cadena = "555-1212"
La segunda es una tabla hash polimórfica:
# let m = Hashtbl . create 3 ;; val m : ( ' _ a , ' _ b ) Hashtbl . t = < abstr > # Hashtbl . add m "Sally Smart" "555-9999" ; Hashtbl . add m "John Doe" "555-1212" ; Hashtbl . add m "J. Random Hacker" "553-1337" ;; - : unidad = () # Hashtbl . find m "John Doe" ;; - : cadena = "555-1212"
El código anterior utiliza la función hash predeterminada de OCaml Hashtbl.hash
, que se define automáticamente para todos los tipos. Para utilizar una función hash modificada, utilice la interfaz functor Hashtbl.Make
para crear un módulo, como con Map
.
Finalmente, los mapas funcionales (representados como árboles binarios equilibrados inmutables):
# módulo StringMap = Map . Make ( String );; ... # deja que m = StringMap . add "Sally Smart" "555-9999" StringMap . empty deja que m = StringMap . add "John Doe" "555-1212" m deja que m = StringMap . add "J. Random Hacker" "553-1337" m ;; val m : string StringMap . t = < abstr > # StringMap . find "John Doe" m ;; - : string = "555-1212"
Tenga en cuenta que para utilizar Map
, debe proporcionar al functor Map.Make
un módulo que defina el tipo de clave y la función de comparación. La biblioteca de terceros ExtLib proporciona una versión polimórfica de mapas funcionales, llamada PMap
, [12] a la que se le asigna una función de comparación al momento de su creación.
Tanto las listas de pares como los mapas funcionales proporcionan una interfaz puramente funcional. Por el contrario, las tablas hash proporcionan una interfaz imperativa. Para muchas operaciones, las tablas hash son significativamente más rápidas que las listas de pares y los mapas funcionales.
El lenguaje de programación OptimJ es una extensión de Java 5. Al igual que Java, OptimJ proporciona mapas, pero OptimJ también proporciona matrices asociativas verdaderas. Las matrices de Java se indexan con números enteros no negativos; las matrices asociativas se indexan con cualquier tipo de clave.
Cadena [ Cadena ] phoneBook = { "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" }; // String[String] no es un tipo Java sino un tipo Optimj: // matriz asociativa de cadenas indexadas por cadenas.// iterar sobre los valores para ( String número : phoneBook ) { System . println ( número ) ; } // La declaración anterior imprime: "555-9999" "555-1212" "553-1337"// iterar sobre las claves para ( String name : phoneBook . keys ) { System . out . println ( name + " -> " + phoneBook [ name ] ); } // phoneBook[name] accede a un valor por una clave (parece un acceso a una matriz de Java) // es decir, phoneBook["John Doe"] devuelve "555-1212"
Por supuesto, es posible definir matrices multidimensionales, mezclar matrices Java y matrices asociativas, mezclar mapas y matrices asociativas.
int [ Cadena ][][ doble ] a ; java . util . Map < Cadena [ Objeto ] , Entero > b ;
Perl 5 tiene soporte integrado a nivel de lenguaje para matrices asociativas. El Perl moderno se refiere a las matrices asociativas como hashes ; el término matriz asociativa se encuentra en documentación antigua, pero se considera algo arcaico. Los hashes de Perl 5 son planos: las claves son cadenas y los valores son escalares. Sin embargo, los valores pueden ser referencias a matrices u otros hashes, y el módulo estándar de Perl 5 Tie::RefHash permite utilizar hashes con claves de referencia.
Una variable hash se marca con un %
sigilo para distinguirla de los tipos de datos escalares, de matriz y de otros. Un literal hash es una lista de clave-valor, y la forma preferida es usar =>
el token de Perl, que es semánticamente casi idéntico a la coma y hace que la asociación clave-valor sea más clara:
mi %phone_book = ( 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' , );
Para acceder a un elemento hash se utiliza la sintaxis $hash_name{$key}
: la clave está entre llaves y el nombre del hash tiene como prefijo $
, lo que indica que el elemento hash en sí es un valor escalar, aunque sea parte de un hash. El valor de $phone_book{'John Doe'}
es '555-1212'
. El %
sigilo solo se utiliza cuando se hace referencia al hash en su totalidad, como cuando se solicita keys %phone_book
.
La lista de claves y valores se puede extraer utilizando las funciones integradas keys
y values
, respectivamente. Por ejemplo, para imprimir todas las claves de un hash:
foreach $nombre ( teclas % agenda_telefonica ) { imprimir $nombre , "\n" ; }
Se pueden iterar pares (clave, valor) utilizando la each
función:
mientras (( $nombre , $número ) = each %phone_book ) { print 'Número para ' , $nombre , ': ' , $número , "\n" ; }
Una "referencia" hash, que es un valor escalar que apunta a un hash, se especifica en forma literal utilizando llaves como delimitadores, con una sintaxis similar a la especificación de un literal hash:
mi $libreta_telefonica = { 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' , };
Se accede a los valores de una referencia hash mediante el operador de desreferenciación:
imprimir $phone_book -> { 'Sally Smart' };
Cuando es necesario hacer referencia al hash contenido en la referencia hash como un todo, como ocurre con la keys
función, la sintaxis es la siguiente:
foreach $nombre ( keys % { $libreta_telefonica }) { print 'Número para ' , $nombre , ': ' , $libreta_telefonica -> { $nombre }, "\n" ; }
Perl 6 , renombrado como "Raku", también tiene soporte integrado a nivel de lenguaje para matrices asociativas, que se conocen como hashes o como objetos que realizan la función "asociativa". Al igual que en Perl 5, los hashes predeterminados de Perl 6 son planos: las claves son cadenas y los valores son escalares. Se puede definir un hash para no convertir todas las claves en cadenas automáticamente: estos se conocen como "hashes de objeto", porque las claves de dichos hashes siguen siendo el objeto original en lugar de una conversión en cadena del mismo.
Una variable hash suele estar marcada con un %
sigilo para distinguirla visualmente de los tipos de datos escalares, de matriz y de otro tipo, y para definir su comportamiento en la iteración. Un literal hash es una lista de clave-valor, siendo la forma preferida el uso del =>
token de Perl, que hace que la asociación de clave-valor sea más clara:
mi %libreta-telefonica = 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' ,;
Para acceder a un elemento hash se utiliza la sintaxis %hash_name{$key}
: la clave está entre llaves y el nombre del hash (tenga en cuenta que el sigilo no cambia, al contrario de Perl 5). El valor de %phone-book{'John Doe'}
es '555-1212'
.
La lista de claves y valores se puede extraer utilizando las funciones integradas keys
y values
, respectivamente. Por ejemplo, para imprimir todas las claves de un hash:
para %phone-book .keys -> $name { decir $ name ; }
De forma predeterminada, al iterar a través de un hash, se obtienen pares clave-valor.
para %phone-book -> $entry { decir "Número para $entry.key(): $entry.value()" ; # usando funciones de interpolación extendidas}
También es posible obtener valores clave y valores de valor alternativos utilizando el kv
método:
para %phone-book . kv -> $nombre , $número { decir "Número para $nombre: $número" ;}
Raku no tiene ninguna referencia. Los hashes se pueden pasar como parámetros únicos que no se aplanan. Si desea asegurarse de que una subrutina solo acepte hashes, use el símbolo % en la firma.
sub lista-libreta-telefonica ( %pb ) { para %pb . kv -> $nombre , $numero { decir "Número para $nombre: $numero" ; }}lista-libreta-telefonica ( %libreta-telefonica );
De acuerdo con la tipificación gradual , los hashes pueden estar sujetos a restricciones de tipo, confinando un conjunto de claves válidas a un tipo determinado.
# Define un hash cuyas claves sólo pueden ser números enteros (tipo "Int"). my %numbersWithNames { Int };# Las claves deben ser números enteros, como en este caso. %numbersWithNames . push ( 1 => "one" );# Esto provocará un error, ya que las cadenas como claves no son válidas. %numbersWithNames . push ( "key" => "two" );
El tipo de matriz incorporado de PHP es, en realidad, una matriz asociativa. Incluso cuando se utilizan índices numéricos, PHP almacena internamente las matrices como matrices asociativas. [13] Por lo tanto, PHP puede tener matrices indexadas numéricamente de forma no consecutiva. Las claves deben ser de tipo entero (los números de punto flotante se truncan a entero) o de tipo cadena, mientras que los valores pueden ser de tipos arbitrarios, incluidos otros arreglos y objetos. Las matrices son heterogéneas: una única matriz puede tener claves de diferentes tipos. Las matrices asociativas de PHP se pueden utilizar para representar árboles, listas, pilas, colas y otras estructuras de datos comunes que no están integradas en PHP.
Una matriz asociativa se puede declarar utilizando la siguiente sintaxis:
$agenda telefónica = array (); $agenda telefónica [ 'Sally Smart' ] = '555-9999' ; $agenda telefónica [ 'John Doe' ] = '555-1212' ; $agenda telefónica [ 'J. Random Hacker' ] = '555-1337' ;// o$libreta telefónica = matriz ( 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '555-1337' , );// o, a partir de PHP 5.4$phonebook = [ 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '555-1337' , ];// o$phonebook [ 'contactos' ][ 'Sally Smart' ][ 'número' ] = '555-9999' ; $phonebook [ 'contactos' ][ 'John Doe' ][ 'número' ] = '555-1212' ; $phonebook [ 'contactos' ][ 'J. Random Hacker' ][ 'número' ] = '555-1337' ;
PHP puede recorrer una matriz asociativa de la siguiente manera:
foreach ( $directorio telefónico como $nombre => $número ) { echo 'Número para ' , $nombre , ': ' , $número , " \n " ; }// Para el último ejemplo de matriz se usa así foreach ( $phonebook [ 'contacts' ] as $name => $num ) { echo 'Name: ' , $name , ', number: ' , $num [ 'number' ], " \n " ; }
PHP tiene un amplio conjunto de funciones para operar con matrices. [14]
Se pueden implementar matrices asociativas que pueden usar objetos como claves, en lugar de cadenas y números enteros, con la SplObjectStorage
clase de la Biblioteca PHP Estándar (SPL). [15]
Pike tiene compatibilidad integrada con matrices asociativas, a las que se denomina asignaciones. Las asignaciones se crean de la siguiente manera:
mapping ( cadena : cadena ) libreta telefónica = ([ "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "555-1337" ]);
El acceso y la comprobación de la presencia en las asignaciones se realiza mediante el operador de indexación. Por lo tanto, phonebook["Sally Smart"]
devolvería la cadena "555-9999"
y phonebook["John Smith"]
devolvería 0.
La iteración a través de un mapeo se puede realizar utilizando foreach
:
foreach ( agenda telefónica ; cadena clave ; cadena valor ) { write ( "%s:%s \n " , clave , valor ); }
O usando un objeto iterador:
Mapeo . Iterador i = get_iterator ( directorio telefónico ); while ( i -> índice ()) { write ( "%s:%s \n " , i -> índice (), i -> valor ()); i -> siguiente (); }
Los elementos de un mapeo se pueden eliminar usando m_delete
, que devuelve el valor del índice eliminado:
cadena sallys_number = m_delete ( agenda telefónica , "Sally Smart" );
En PostScript , las matrices asociativas se denominan diccionarios. En PostScript de nivel 1, deben crearse explícitamente, pero en el nivel 2 se introdujo la declaración directa mediante una sintaxis de corchetes dobles:
% Declaración de nivel 1 3 dict dup begin /red (rojo) def /green (verde) def /blue (azul) def end % Declaración de nivel 2 << /rojo (rot) /verde (gruen) /azul (blau) >> % Ambos métodos dejan el diccionario en la pila de operandos
Se puede acceder a los diccionarios directamente, usando get
, o implícitamente, colocando el diccionario en la pila de diccionarios usando begin
:
% Con los dos diccionarios anteriores aún en la pila de operandos /red get print % genera 'rot' comienza verde imprimir % salidas 'vert' fin
El contenido del diccionario se puede iterar mediante el uso de forall
, aunque no en ningún orden particular:
% Ejemplo de nivel 2 << /Este 1 /Aquello 2 /Otro 3 >> { exch =print ( es ) print == } forall
Lo cual puede dar como resultado:
Eso es 2 Esto es 1 El otro es 3
Los diccionarios se pueden ampliar (hasta su tamaño definido solo en el Nivel 1) o modificar usando put
, y las entradas se pueden eliminar usando undef
:
% define un diccionario para reutilizarlo fácilmente: /MyDict << /rouge (rojo) /vert (gruen) >> def % añadir a MyDict /bleu (azul) poner % cámbialo MyDict /vert (verde) ponlo % eliminar algo MyDict /rouge undef
Algunas versiones de Prolog incluyen utilidades de diccionario ("dict"). [16]
En Python , las matrices asociativas se denominan " diccionarios ". Los literales de diccionario se delimitan mediante llaves:
directorio telefónico = { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "553-1337" , }
Se puede acceder a los elementos del diccionario utilizando el operador de indexación de matriz:
>>> directorio telefónico [ "Sally Smart" ] '555-9999'
Bucle que itera a través de todas las claves del diccionario:
>>> para introducir la clave en la agenda : ... imprimir ( clave , agenda [ clave ]) Sally Smart 555 - 9999 J. Random Hacker 553 - 1337 John Doe 555 - 1212
Iterando a través de tuplas (clave, valor):
>>> para clave , valor en la agenda telefónica . elementos ( ): ... print ( clave , valor ) Sally Smart 555 - 9999 J. Random Hacker 553 - 1337 John Doe 555 - 1212
Las claves de diccionario se pueden eliminar individualmente mediante la del
instrucción. El valor correspondiente se puede devolver antes de que se elimine el par clave-valor mediante el método "pop" del tipo "dict":
>>> del phonebook [ "John Doe" ] >>> val = phonebook . pop ( "Sally Smart" ) >>> phonebook . keys () # Solo queda una clave [ 'J. Random Hacker' ]
Python 2.7 y 3.x también admiten comprensiones de diccionarios (similares a las comprensiones de listas ), una sintaxis compacta para generar un diccionario a partir de cualquier iterador:
>>> square_dict = { i : i * i para i en rango ( 5 )} >>> square_dict { 0 : 0 , 1 : 1 , 2 : 4 , 3 : 9 , 4 : 16 } >>> { clave : valor para clave , valor en la libreta de teléfonos . items () si "J" en clave } { 'J. Random Hacker' : '553-1337' , 'John Doe' : '555-1212' }
En sentido estricto, un diccionario es un superconjunto de una matriz asociativa, ya que ni las claves ni los valores están limitados a un único tipo de datos. Se podría pensar en un diccionario como una "lista asociativa" utilizando la nomenclatura de Python. Por ejemplo, lo siguiente también es válido:
directorio telefónico = { "Sally Smart" : "555-9999" , "John Doe" : Ninguno , "J. Random Hacker" : - 3.32 , 14 : "555-3322" , }
Las claves del diccionario deben ser de un tipo de datos inmutable . En Python, las cadenas son inmutables debido a su método de implementación.
En Red, el tipo de datos integrado map!
[17] proporciona una matriz asociativa que asigna valores de tipos de claves de palabras, cadenas y escalares a valores de cualquier tipo. Se utiliza una tabla hash internamente para realizar búsquedas.
Un mapa se puede escribir como un literal, como #(key1 value1 key2 value2 ...)
, o se puede crear usando make map! [key1 value1 key2 value2 ...]
:
Rojo [ Título: "Mi mapa" ]my-map: ¡crea un mapa! [ "Sally Smart" "555-9999" "John Doe" "555-1212" "J. Random Hacker" "553-1337" ]; Red conserva las mayúsculas y minúsculas tanto para las claves como para los valores, sin embargo, las búsquedas no distinguen entre mayúsculas y minúsculas de forma predeterminada; es posible forzar la distinción entre mayúsculas y minúsculas utilizando el refinamiento <code>/case</code> para <code>select</code> y <code>put</code>.;Por supuesto, es posible utilizar valores <code>word!</code> como claves, en cuyo caso generalmente se prefiere utilizar valores <code>set-word!</code> al crear el mapa, pero se puede utilizar cualquier tipo de palabra para la búsqueda o creación.my-other-map: ¡crea un mapa! [ foo: 42 bar: false ]; Tenga en cuenta que el bloque no se reduce ni se evalúa de ninguna manera, por lo tanto, en el ejemplo anterior, la clave <code>bar</code> está asociada con el valor <code>word!</code> <code>false</code> en lugar del valor <code>logic!</code> false; se puede usar la sintaxis literal si se desea esto último:my-other-map: ¡crea un mapa! [ foo: 42 bar: # [ false ]]; o se pueden agregar claves después de la creación:mi-otro-mapa: ¡crea un mapa! [ foo: 42 ] mi-otro-mapa /bar: falsoLa búsqueda se puede escribir utilizando la notación <code>path!</code> o utilizando la acción <code>select</code>:seleccione mi-mapa "Sally Smart" mi-otro-mapa /foo; También puedes recorrer todas las claves y valores con <code>foreach</code>:foreach [ clave valor ] my-map [ imprimir [ clave "está asociada a" valor ] ];Se puede eliminar una clave usando <code>remove/key</code>:eliminar /key mi-mapa "Sally Smart"
En REXX , las matrices asociativas se denominan "variables de raíz" o "variables compuestas".
CLAVE = 'Sally Smart'
AGENDA TELEFÓNICA . CLAVE = '555-9999'
CLAVE = 'John Doe'
AGENDA TELEFÓNICA . CLAVE = '555-1212'
CLAVE = 'J. Random Hacker'
AGENDA TELEFÓNICA . CLAVE = '553-1337'
Las variables de raíz con claves numéricas suelen empezar en 1 y van aumentando a partir de ahí. La variable de raíz con clave 0 por convención contiene el número total de elementos de la raíz:
NOMBRE . 1 = 'Sally Smart'
NOMBRE . 2 = 'John Doe'
NOMBRE . 3 = 'J. Random Hacker'
NOMBRE . 0 = 3
REXX no tiene una forma sencilla de acceder automáticamente a las claves de una variable raíz; y normalmente las claves se almacenan en una matriz asociativa separada, con claves numéricas.
En Ruby una tabla hash se utiliza de la siguiente manera:
directorio telefónico = { 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' } directorio telefónico [ 'John Doe' ]
Ruby admite bucles hash e iteraciones con la siguiente sintaxis:
irb(main):007:0> ### iterar sobre claves y valores irb(main):008:0* phonebook . each { | key , value | puts key + " => " + value } Sally Smart => 555-9999 John Doe => 555-1212 J. Random Hacker => 553-1337 => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"} irb(main):009:0> ### iterar solo claves irb(main):010:0* phonebook . each_key { | key | pone clave } Sally Smart John Doe J. Random Hacker => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"} irb(main):011:0> ### itera solo valores irb(main):012:0* directorio telefónico . each_value { | valor | pone valor } 555-9999 555-1212 553-1337 => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"}
Ruby también admite muchas otras operaciones útiles en hashes, como fusionar hashes, seleccionar o rechazar elementos que cumplen ciertos criterios, invertir (intercambiar las claves y los valores) y aplanar un hash en una matriz.
La biblioteca estándar de Ruststd::collections::HashMap
proporciona un mapa hash ( ) y un mapa B-treestd::collections::BTreeMap
( ). Comparten varios métodos con los mismos nombres, pero tienen diferentes requisitos para los tipos de claves que se pueden insertar. El HashMap
requiere que las claves implementen los rasgos Eq
( relación de equivalencia ) y Hash
(capacidad de hash) y almacena las entradas en un orden no especificado, y el BTreeMap
requiere el rasgo Ord
( orden total ) para sus claves y almacena las entradas en un orden definido por el tipo de clave. El orden se refleja en los iteradores predeterminados.
use std :: colecciones :: HashMap ; deje que mut libreta_telefonica = HashMap :: new (); libreta_telefonica.insert ( " Sally Smart" , " 555-9999" ); libreta_telefonica.insert ( " John Doe" , "555-1212" ) ; libreta_telefonica.insert ( "J. Random Hacker" , " 555-1337 " );
Los iteradores predeterminados visitan todas las entradas como tuplas. Los HashMap
iteradores visitan las entradas en un orden no especificado y el BTreeMap
iterador visita las entradas en el orden definido por el tipo de clave.
para ( nombre , número ) en & phone_book { println! ( "{} {}" , nombre , número ); }
También hay un iterador para claves:
para el nombre en la libreta telefónica . keys () { println! ( "{}" , nombre ); }
S-Lang tiene un tipo de matriz asociativa:
libreta telefónica = Assoc_Type[];directorio telefónico["Sally Smart"] = "555-9999"directorio telefónico["John Doe"] = "555-1212"directorio telefónico["J. Random Hacker"] = "555-1337"
También puedes recorrer una matriz asociada de varias maneras:
foreach nombre (guía telefónica) {vmessage ("%s %s", nombre, libreta telefónica[nombre]);}
Para imprimir una lista ordenada, es mejor aprovechar el fuerte soporte de S-lang para matrices estándar:
llaves = assoc_get_keys(agenda telefónica);i = array_sort(claves);vals = assoc_get_values(agenda telefónica);array_map (Void_Type, &vmessage, "%s %s", claves[i], valores[i]);
Scala proporciona una Map
clase inmutable como parte del scala.collection
marco:
val phonebook = Mapa ( "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" )
La inferencia de tipos de Scala decidirá que se trata de un Map[String, String]
. Para acceder a la matriz:
directorio telefónico . obtener ( "Sally Smart" )
Esto devuelve un Option
tipo, el equivalente de Scala de la mónada Maybe en Haskell.
En Smalltalk se Dictionary
utiliza:
agenda telefónica := Diccionario nuevo . agenda telefónica en: 'Sally Smart' puesto: '555-9999' . agenda telefónica en: 'John Doe' puesto: '555-1212' . agenda telefónica en: 'J. Random Hacker' puesto: '553-1337' .
Para acceder a una entrada, el mensaje #at:
se envía al objeto del diccionario:
directorio telefónico en: 'Sally Smart'
Lo que da:
'555-9999'
Un diccionario realiza un hash o una comparación en función de la igualdad y marca tanto la clave como el valor como referencias fuertes . Existen variantes en las que se realiza un hash o una comparación en función de la identidad (IdentityDictionary) o se mantienen las referencias débiles (WeakKeyDictionary / WeakValueDictionary). Debido a que todos los objetos implementan #hash, cualquier objeto puede usarse como clave (y, por supuesto, también como valor).
SNOBOL es uno de los primeros lenguajes de programación (si no el primero) en utilizar matrices asociativas. Las matrices asociativas en SNOBOL se denominan tablas.
AGENDA TELEFÓNICA = TABLA () AGENDA TELEFÓNICA [ 'Sally Smart' ] = '555-9999' AGENDA TELEFÓNICA [ 'John Doe' ] = '555-1212' AGENDA TELEFÓNICA [ 'J. Random Hacker' ] = '553-1337'
El estándar SML'97 del lenguaje de programación Standard ML no proporciona ningún contenedor asociativo. Sin embargo, varias implementaciones de Standard ML sí proporcionan contenedores asociativos.
La biblioteca de la popular implementación del Standard ML de Nueva JerseyORD_MAP
(SML/NJ) proporciona una firma (algo así como una "interfaz"), , que define una interfaz común para matrices asociativas funcionales ordenadas (inmutables). Hay varios funtores generales BinaryMapFn
— , ListMapFn
, RedBlackMapFn
y SplayMapFn
— que le permiten crear el tipo correspondiente de mapa ordenado (los tipos son un árbol binario de búsqueda autoequilibrado , una lista de asociación ordenada , un árbol rojo-negro y un árbol de dispersión , respectivamente) utilizando una estructura proporcionada por el usuario para describir el tipo de clave y el comparador. El funtor devuelve una estructura de acuerdo con la ORD_MAP
interfaz. Además, hay dos módulos predefinidos para matrices asociativas que emplean claves enteras: IntBinaryMap
y IntListMap
.
- estructura StringMap = BinaryMapFn ( estructura tipo ord_key = cadena val comparar = String . comparar fin ); estructura StringMap : ORD_MAP- val m = StringMap . insert ( StringMap . empty , "Sally Smart" , "555-9999" ) val m = StringMap . insert ( m , "Juan Pérez" , "555-1212" ) val m = StringMap . insert ( m , "J. Hacker aleatorio" , "553-1337" ); val m = T { cnt = 3 , clave = "Juan Pérez" , izquierda = T { cnt = 1 , clave = "J. Hacker aleatorio" , izquierda = E , derecha = E , valor = "553-1337" }, derecha = T { cnt = 1 , clave = "Sally Smart" , izquierda = E , derecha = E , valor = "555-9999" }, valor = "555-1212" } : cadena StringMap . mapa - StringMap . find ( m , "John Doe" ); val it = SOME "555-1212" : cadena opción
SML/NJ también proporciona una tabla hash polimórfica:
- excepción No encontrado ; excepción No encontrado - val m : ( cadena , cadena ) HashTable . hash_table = HashTable . mkTable ( HashString . hashString , op =) ( 3 , No encontrado ); val m = HT { eq_pred = fn , hash_fn = fn , n_items = ref 0 , no_encontrado = No encontrado ( - ), tabla = ref [ | NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL ,... | ]} : ( cadena , cadena ) HashTable . hash_table - HashTable . insert m ( "Sally Smart" , "555-9999" ); val it = () : unidad - HashTable . insert m ( "John Doe" , "555-1212" ); val it = () : unidad - HashTable . insert m ( "J. Random Hacker" , "553-1337" ); val it = () : unidad HashTable . find m "John Doe" ; (* devuelve NONE si no se encuentra *) val it = SOME "555-1212" : cadena option - HashTable . lookup m "John Doe" ; (* lanza la excepción si no se encuentra *) val it = "555-1212" : cadena
También se admiten tablas hash monomórficas mediante el uso del HashTableFn
functor.
Otra implementación de Standard ML, Moscow ML , también proporciona algunos contenedores asociativos. En primer lugar, proporciona tablas hash polimórficas en la Polyhash
estructura. Además, algunos mapas funcionales de la biblioteca SML/NJ mencionada anteriormente están disponibles como estructuras Binarymap
, Splaymap
y .Intmap
Hay dos funciones de Tcl que admiten la semántica de matriz asociativa. Una "matriz" es una colección de variables. Un "dict" es una implementación completa de matrices asociativas.
establecer { agenda telefónica ( Sally Smart )} 555 - 9999 establecer john { John Doe } establecer agenda telefónica ( $john ) 555 - 1212 establecer { agenda telefónica ( J. Random Hacker )} 553 - 1337
Si hay un carácter de espacio en el nombre de la variable, el nombre debe agruparse utilizando llaves (no se realiza ninguna sustitución) o comillas dobles (se realiza una sustitución).
Como alternativa, se pueden configurar varios elementos de una matriz con un solo comando, presentando sus asignaciones como una lista (las palabras que contienen espacios en blanco aparecen entre llaves):
conjunto de matrices de la agenda telefónica [ lista { Sally Smart } 555 - 9999 { John Doe } 555 - 1212 { J. Random Hacker } 553 - 1337 ]
Para acceder a una entrada de la matriz y ponerla en la salida estándar:
pone $phonebook ( Sally \ Smart )
Que devuelve este resultado:
555-9999
Para recuperar la matriz completa como diccionario:
matriz obtener agenda telefónica
El resultado puede ser (el orden de las claves no se especifica, no porque el diccionario no esté ordenado, sino porque la matriz sí lo está):
{ Sally Smart } 555-9999 { J. Hacker aleatorio } 553-1337 { John Doe } 555-1212
establecer libreta telefónica [ dict create { Sally Smart } 555 - 9999 { John Doe } 555 - 1212 { J. Random Hacker } 553 - 1337 ]
Para buscar un artículo:
dict obtener $phonebook { John Doe }
Para iterar a través de un diccionario:
foreach { nombre numero } $phonebook { pone "nombre: $nombre\nnumero: $numero" }
Visual Basic puede utilizar la clase Dictionary de Microsoft Scripting Runtime (que se incluye con Visual Basic 6). No existe una implementación estándar común para todas las versiones:
' Requiere una referencia a SCRRUN.DLL en las Propiedades del proyecto Dim phoneBook As New Dictionary phoneBook . Agregar "Sally Smart" , "555-9999" phoneBook . Elemento ( "John Doe" ) = "555-1212" phoneBook ( "J. Random Hacker" ) = "553-1337" Para cada nombre En phoneBook MsgBox nombre & " = " & phoneBook ( nombre ) Siguiente
Visual Basic .NET utiliza las clases de colección proporcionadas por .NET Framework .
El siguiente código demuestra la creación y población de un diccionario (consulte el ejemplo de C# en esta página para obtener información adicional):
Dim dic Como nuevo sistema . Colecciones . Genérico . Diccionario ( De cadena , cadena ) dic . Add ( "Sally Smart" , "555-9999" ) dic ( "John Doe" ) = "555-1212" dic . Item ( "J. Random Hacker" ) = "553-1337"
Una sintaxis alternativa sería utilizar un inicializador de colección , que compila en llamadas individuales a Add
:
Dim dic como nuevo sistema . Colecciones . Diccionario ( de cadena , cadena ) de { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" } }
Ejemplo que demuestra el acceso (ver acceso en C#):
Dim sallyNumber = dic ( "Sally Smart" ) o Dim sallyNumber = dic . Item ( "Sally Smart" )
Resultado oscuro como cadena = Nada Dim sallyNumber = Si ( dic . TryGetValue ( "Sally Smart" , resultado ), resultado , "n/a" )
Ejemplo que demuestra la enumeración (ver #enumeraciónC#):
' recorre la colección y muestra cada entrada. Para cada kvp como KeyValuePair ( Of String , String ) En dic Console . WriteLine ( "El número de teléfono de {0} es {1}" , kvp . Key , kvp . Value ) Siguiente
A diferencia de muchos otros intérpretes de línea de comandos , Windows PowerShell tiene soporte integrado a nivel de lenguaje para definir matrices asociativas:
$phonebook = @{ 'Sally Smart' = '555-9999' ; 'Juan Pérez' = '555-1212' ; 'J. Hacker aleatorio' = '553-1337' }
Al igual que en JavaScript, si el nombre de la propiedad es un identificador válido, se pueden omitir las comillas:
$miOtroObjeto = @{ foo = 42 ; bar = $falso }
Las entradas se pueden separar mediante un punto y coma o una nueva línea:
$myOtherObject = @{ foo = 42 bar = $false ; zaz = 3 }
Las claves y los valores pueden ser cualquier tipo de objeto .NET :
$ahora = [FechaHora] :: Ahora $mañana = $ahora . AddDays ( 1 ) $ProcessDeletionSchedule = @{ ( Obtener-Proceso bloc de notas ) = $ahora ( Obtener-Proceso calc ) = $mañana }
También es posible crear una matriz asociativa vacía y agregarle entradas individuales, o incluso otras matrices asociativas, más adelante:
$agenda telefónica = @{} $agenda telefónica += @{ 'Sally Smart' = '555-9999' } $agenda telefónica += @{ 'John Doe' = '555-1212' ; 'J. Hacker aleatorio' = '553-1337' }
También se pueden agregar nuevas entradas utilizando el operador de índice de matriz, el operador de propiedad o el Add()
método del objeto .NET subyacente:
$agenda telefónica = @{} $agenda telefónica [ 'Sally Smart' ] = '555-9999' $agenda telefónica . 'John Doe' = '555-1212' $agenda telefónica . Add ( 'J. Random Hacker' , '553-1337' )
Para desreferenciar objetos asignados, se puede utilizar el operador de índice de matriz, el operador de propiedad o la propiedad parametrizada Item()
del objeto .NET:
$phonebook [ 'Sally Smart' ] $phonebook . 'John Doe' $phonebook . Item ( 'J. Random Hacker' )
Puede recorrer una matriz asociativa de la siguiente manera:
$phonebook . Claves | foreach { "Número para {0}: {1}" -f $_ , $phonebook . $_ }
Se puede eliminar una entrada utilizando el Remove()
método del objeto .NET subyacente:
$phonebook . Eliminar ( 'Sally Smart' )
Se pueden agregar tablas hash:
$hash1 = @{ a = 1 ; b = 2 } $hash2 = @{ c = 3 ; d = 4 } $hash3 = $hash1 + $hash2
Many data serialization formats also support associative arrays (see this table)
In JSON, associative arrays are also referred to as objects. Keys can only be strings.
{ "Sally Smart": "555-9999", "John Doe": "555-1212", "J. Random Hacker": "555-1337"}
YAML associative arrays are also called map elements or key-value pairs. YAML places no restrictions on the types of keys; in particular, they are not restricted to being scalar or string values.
Sally Smart: 555-9999John Doe: 555-1212J. Random Hacker: 555-1337
hcreate()
, hdestroy()
and hsearch()