Comparación de lenguajes de programación (arreglo asociativo)

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 .

Soporte de idiomas

La siguiente es una comparación de matrices asociativas (también "mapeo", "hash" y "diccionario") en varios lenguajes de programación.

AWK

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 ]; } }

do

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.

DO#

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.Immutablepaquete 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.

Creación

A continuación se muestran tres formas de completar un diccionario mutable:

  • el Addmétodo que agrega una clave y un valor y lanza una excepción si la clave ya existe en el diccionario;
  • asignar al indexador, que sobrescribe cualquier valor existente, si está presente; y
  • asignando a la propiedad de respaldo del indexador, para el cual el indexador es azúcar sintáctico (no aplicable a C#, consulte los ejemplos de F# o VB.NET).
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" } };                  

Acceso mediante clave

Los valores se recuperan principalmente utilizando el indexador (que genera una excepción si la clave no existe) y el TryGetValuemé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 sallyNumbervalor ahora contendrá la cadena "555-9999".

Enumeración

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++

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::stringvalores 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::mapclase se basa en plantillas, lo que permite que los tipos de datos de las claves y los valores sean diferentes para las distintas mapinstancias. Para una instancia determinada de la mapclase, las claves deben ser del mismo tipo base. Lo mismo debe ser cierto para todos los valores. Aunque std::mapnormalmente 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.

Cobra

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]"

Lenguaje de marcado ColdFusion

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

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" ) ;

Delfos

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

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.

Listas de claves

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 listsmó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/3función:

{_, Teléfono } = listas : keyfind ( "Sally Smith" , 1 , Libreta telefónica ), io : formato ( "Número de teléfono: ~s~n " , [ Teléfono ]).      

Diccionarios

Los diccionarios se implementan en el dictmódulo de la biblioteca estándar. Se crea un nuevo diccionario mediante la dict:new/0función y se almacenan nuevos pares clave/valor mediante la dict:store/3funció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/2funció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 orddictmódulo, que implementa diccionarios ordenados, y el módulo gb_trees, que implementa árboles balanceados generales.

Mapas

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/2funció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" }   

F#

Mapa<'Clave,'Valor>

En tiempo de ejecución, F# proporciona el Collections.Map<'Key,'Value>tipo, que es un árbol AVL inmutable .

Creación

El siguiente ejemplo llama al Mapconstructor, 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             
Acceso mediante clave

Los valores se pueden buscar a través de uno de los Mapmiembros, como su indexador o Itempropiedad (que genera una excepción si la clave no existe) o la TryFindfunció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 sallyNumbervalor contendría la cadena "555-9999".

Diccionario<'TKey,'TValue>

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>

Creación

La dictfunció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"         
Acceso mediante clave

IDictionaryLas instancias tienen un indexador que se utiliza de la misma manera que Map, aunque el equivalente a TryFindes 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"              

Enumeración

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 )         

Fox Pro

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.

Ir

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 ) }      

Haskell

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 .

Java

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 getmé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 HashMapclase. 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 TreeMapclase (que implementa la subinterfaz SortedMap), sin cambiar la definición de la phoneBookvariable, ni el resto del código, ni utilizar otras estructuras de datos subyacentes que implementen la Mapinterfaz.

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 Objectclase 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 Comparableinterfaz; o bien se debe proporcionar uno personalizado Comparatoren 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

JavaScript (y su versión estandarizada, ECMAScript ) es un lenguaje orientado a objetos basado en prototipos .

Mapa y WeakMap

El JavaScript moderno maneja matrices asociativas, utilizando las clases Mapy 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).

Creación

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" );       
Acceso mediante clave

El acceso a un elemento del mapa se puede realizar con el getmétodo:

const sallyNumber = phoneBook . get ( "Sally Smart" );   

En este ejemplo, el valor sallyNumberahora contendrá la cadena "555-9999".

Enumeración

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" ) ;

Objeto

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.setPrototypeOffunció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/ WeakMapson 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.

Julia

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 )

KornShell 93 y shells compatibles

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" ] } ;

Ceceo

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 consmatrices asociativas . Las claves y los valores no necesitan ser del mismo tipo dentro de una lista. Lisp y Scheme proporcionan operadores como este assocpara 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 aconsse 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 conslas 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 pushtambié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 NILvalor.

( directorio telefónico de la asociación "John Doe" : prueba #' cadena= )    

Dos generalizaciones de assocexist: assoc-ifespera una función de predicado que prueba la clave de cada entrada, devolviendo la primera entrada para la cual el predicado produce un NILvalor distinto al invocarse. assoc-if-notinvierte 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-ifexisten 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 positiony 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-tablefunció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 :testfunción clave se limita a entidades distinguibles: el estándar Common Lisp solo exige el soporte de eq, eql, equaly 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 gethashfunció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 gethashen realidad devuelve dos valores: el valor o valor sustituto de la clave y un indicador booleano, que retorna Tsi la tabla hash contiene la clave y NILpara 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 remhashpara eliminar la entrada asociada a una clave.

( remhash de la guía telefónica de "J. Random Hacker" )  

clrhashvacía completamente la tabla hash.

( clrhash directorio telefónico ) 

La maphashfunción dedicada se especializa en iterar tablas hash.

( maphash #' ( lambda ( clave valor ) ( formato T "~&~s => ~s" clave valor )) libreta telefónica )         

Alternativamente, el loopconstructo 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.

PCL

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.

Lua

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

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]

PAPERAS

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),!

Objetivo-C (Cocoa/GNUstep)

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 NSCopyingprotocolo. 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 NSFastEnumerationconstrucció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" ];    

OCaml

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.Makepara 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.Makeun 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.

Optim J

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

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 keysy 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 eachfunció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 keysfunción, la sintaxis es la siguiente:

foreach $nombre ( keys % { $libreta_telefonica }) { print 'Número para ' , $nombre , ': ' , $libreta_telefonica -> { $nombre }, "\n" ; }         

Perl 6 (Raku)

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 keysy 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 kvmé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" );

PHP

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 SplObjectStorageclase de la Biblioteca PHP Estándar (SPL). [15]

Lucio

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" );    

Posdata

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   

Prólogo

Algunas versiones de Prolog incluyen utilidades de diccionario ("dict"). [16]

Pitón

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 delinstrucció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.

Rojo

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"

Rexxo

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.

Rubí

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.

Óxido

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 HashMaprequiere 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 BTreeMaprequiere 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 HashMapiteradores visitan las entradas en un orden no especificado y el BTreeMapiterador 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 ); }      

Jerga

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]);

Escala

Scala proporciona una Mapclase inmutable como parte del scala.collectionmarco:

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 Optiontipo, el equivalente de Scala de la mónada Maybe en Haskell.

Charla informal

En Smalltalk se Dictionaryutiliza:

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

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'

ML estándar

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, RedBlackMapFny 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_MAPinterfaz. Además, hay dos módulos predefinidos para matrices asociativas que emplean claves enteras: IntBinaryMapy 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 HashTableFnfunctor.

Otra implementación de Standard ML, Moscow ML , también proporciona algunos contenedores asociativos. En primer lugar, proporciona tablas hash polimórficas en la Polyhashestructura. Además, algunos mapas funcionales de la biblioteca SML/NJ mencionada anteriormente están disponibles como estructuras Binarymap, Splaymapy .Intmap

Tcl

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.

formación

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        

dictado

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

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

Visual Basic .NET utiliza las clases de colección proporcionadas por .NET Framework .

Creación

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" } }              

Acceso mediante clave

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" )           

Enumeración

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           

Windows PowerShell

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

Compatibilidad con formatos de serialización de datos

Many data serialization formats also support associative arrays (see this table)

JSON

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

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

References

  1. ^ here, archived here, with the source code available here. POSIX 1003.1-2001 describes the functions hcreate(), hdestroy() and hsearch()
  2. ^ "uthash: a hash table for C structures". Github. Retrieved 3 August 2020.
  3. ^ "Hash Tables". Gnome Developer. Retrieved 3 August 2020.
  4. ^ "Associative Arrays - D Programming Language". dlang.org. Retrieved 2021-05-07.
  5. ^ "Erlang -- maps". erlang.org. Retrieved 2021-03-07.
  6. ^ "Common Lisp the Language, 2nd Edition: 15.6. Association Lists". Carnegie Mellon University. Retrieved 3 August 2020.
  7. ^ "Association (<-...->)—Wolfram Language Documentation". reference.wolfram.com.
  8. ^ "Key—Wolfram Language Documentation". reference.wolfram.com.
  9. ^ "Keys—Wolfram Language Documentation". reference.wolfram.com.
  10. ^ "Values—Wolfram Language Documentation". reference.wolfram.com.
  11. ^ "NSFastEnumeration Protocol Reference". Mac Developer Library. 2011. Archived from the original on 13 March 2016. Retrieved 3 August 2020.
  12. ^ "Module PMap". Ocaml-extlib. 2008. Archived from the original on 11 December 2008. Retrieved 3 August 2020.
  13. ^ About the implementation of Arrays in PHP
  14. ^ "Matrices". PHP.net . Consultado el 3 de agosto de 2020 .
  15. ^ "La clase SplObjectStorage". PHP.net . Consultado el 3 de agosto de 2020 .
  16. ^ "Dicts: estructuras con argumentos nombrados"
  17. ^ "Mapa! tipo de datos". doc.red-lang.org .
Retrieved from "https://en.wikipedia.org/w/index.php?title=Comparison_of_programming_languages_(associative_array)&oldid=1241597169"