¿Hay diccionarios en javascript como Python?

100

necesito hacer un diccionario en javascript como este

No recuerdo la notación exacta, pero era algo como:

states_dictionary={ CT=[alex,harry], AK=[liza,alex], TX=[fred, harry] ........ }

¿Existe tal cosa en javascript?

l --''''''--------- '' '' '' '' '' '
fuente
2
Vea esta pregunta: stackoverflow.com/questions/130543/…
Manoj Govindan
5
La respuesta que aceptó es muy incorrecta.
Esben Skov Pedersen
@EsbenSkovPedersen ¿Qué errores notó en esa respuesta?
Anderson Green
Veo que está editado después de que comenté. Parece: faltaba
Esben Skov Pedersen
2
Lea la respuesta más reciente para ES6 Maps stackoverflow.com/a/32993723/1993919 (comentando por la misma razón por la que se publicó)
Old Badman Gray

Respuestas:

130

Esta es una publicación antigua, pero pensé que debería proporcionar una respuesta ilustrada de todos modos.

Utilice la notación de objetos de JavaScript. Al igual que:

states_dictionary={ 
     "CT":["alex","harry"], 
     "AK":["liza","alex"], 
     "TX":["fred", "harry"]
};

Y para acceder a los valores:

states_dictionary.AK[0] //which is liza

o puede usar la notación de objeto literal de JavaScript, por lo que las claves no requieren estar entre comillas:

states_dictionary={ 
     CT:["alex","harry"], 
     AK:["liza","alex"], 
     TX:["fred", "harry"]
};
Jefe
fuente
11
Vale la pena señalar que el primer ejemplo debería producir el mismo objeto en ambos idiomas usando exactamente la misma sintaxis excepto el cierre ';'. states_dictionary = {"CT": ["alex", "harry"], "AK": ["liza", "alex"], "TX": ["fred", "harry"]}
Denis C
Estoy más acostumbrado a la notación de objetos literal, ya que accedes a ellos de la misma manera ¿cuál es la diferencia entre los dos?
John Demetriou
2
@JohnDemetriou la principal diferencia es que las claves de notación de objetos javascript deben ser cadenas (entre comillas dobles ""). La notación de objeto es como se ve en JSON para el intercambio de datos y se inspiró en la notación de objeto literal; Vale la pena señalar que JSON generalmente se usa en contexto de cadena
Jefe
2
En realidad, Python permite puntos y comas que terminan en declaraciones, por lo que el primer ejemplo es completamente válido tanto en Python como en JavaScript
celticminstrel
Si el valor proviene del usuario, entonces se debe tener cuidado al usarlo Object.hasOwnProperty.call(dictionary, key)(de lo contrario, el usuario puede ingresar un valor de valueOf y dictionary['valueOf']devuelve la Object.valueOf()función que pertenece al prototipo de Object, que probablemente no sea lo que su código esperaría: error potencial o problema de seguridad ). Si la clave no es un tipo de cadena, entonces se debe tener cuidado, de lo contrario, las conversiones numéricas implícitas y toString le causarán problemas. El Maptipo ES6 se ha diseñado para proporcionar una funcionalidad ampliada para los diccionarios.
robocat
50

No hubo matrices asociativas reales en Javascript hasta 2015 (lanzamiento de ECMAScript 6). Desde entonces, puede utilizar el objeto Map como indica Robocat. Busque los detalles en MDN . Ejemplo:

let map = new Map();
map.set('key', {'value1', 'value2'});
let values = map.get('key');

Sin soporte para ES6, puede intentar usar objetos:

var x = new Object();
x["Key"] = "Value";

Sin embargo, con los objetos no es posible utilizar propiedades de matriz o métodos típicos como array.length. Al menos es posible acceder a la "matriz de objetos" en un bucle for-in.

Alex
fuente
3
¿Y la actuación? ¿Buscar una clave en un objeto es un tiempo constante?
Saher Ahwal
5
Dado que o ["clave"] es equivalente a o.key en Javascript, el rendimiento es casi el mismo. Sin embargo, el rendimiento depende del motor Javascript / navegador web. Hay muchas diferencias entre estos, especialmente en las versiones anteriores.
Alex
ECMAScript 6 define un objeto Map oficial (es decir, "No hay matrices asociativas reales en Javascript" ahora es incorrecto).
robocat
18

Me doy cuenta de que esta es una pregunta antigua, pero aparece en Google cuando busca 'diccionarios javascript', por lo que me gustaría agregar a las respuestas anteriores que en ECMAScript 6, Mapse introdujo el objeto oficial , que es un diccionario implementación:

var dict = new Map();
dict.set("foo", "bar");

//returns "bar"
dict.get("foo");

A diferencia de los objetos normales de javascript, permite cualquier objeto como clave:

var foo = {};
var bar = {};
var dict = new Map();
dict.set(foo, "Foo");
dict.set(bar, "Bar");

//returns "Bar"
dict.get(bar);

//returns "Foo"
dict.get(foo);

//returns undefined, as {} !== foo and {} !== bar
dict.get({});
JimmyMcHoover
fuente
Funciona para mí, es bueno usar un método ES6 más limpio. ¡Gracias! Seguimiento, ¿sabemos alguna forma de "conjunto masivo ()", por ejemplo, como python dict = { key: value)?
Joe Sadoski
10

He creado un diccionario simple en JS aquí:

function JSdict() {
    this.Keys = [];
    this.Values = [];
}

// Check if dictionary extensions aren't implemented yet.
// Returns value of a key
if (!JSdict.prototype.getVal) {
    JSdict.prototype.getVal = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        for (var i = 0; i < this.Keys.length; i++) {
            if (this.Keys[i] == key) {
                return this.Values[i];
            }
        }
        return "Key not found!";
    }
}


// Check if dictionary extensions aren't implemented yet.
// Updates value of a key
if (!JSdict.prototype.update) {
    JSdict.prototype.update = function (key, val) {
        if (key == null || val == null) {
            return "Key or Value cannot be null";
        }
        // Verify dict integrity before each operation
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Values[i] = val;
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}



// Check if dictionary extensions aren't implemented yet.
// Adds a unique key value pair
if (!JSdict.prototype.add) {
    JSdict.prototype.add = function (key, val) {
        // Allow only strings or numbers as keys
        if (typeof (key) == "number" || typeof (key) == "string") {
            if (key == null || val == null) {
                return "Key or Value cannot be null";
            }
            if (keysLength != valsLength) {
                return "Dictionary inconsistent. Keys length don't match values!";
            }
            var keysLength = this.Keys.length;
            var valsLength = this.Values.length;
            for (var i = 0; i < keysLength; i++) {
                if (this.Keys[i] == key) {
                    return "Duplicate keys not allowed!";
                }
            }
            this.Keys.push(key);
            this.Values.push(val);
        }
        else {
            return "Only number or string can be key!";
        }
    }
}

// Check if dictionary extensions aren't implemented yet.
// Removes a key value pair
if (!JSdict.prototype.remove) {
    JSdict.prototype.remove = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Keys.shift(key);
                this.Values.shift(this.Values[i]);
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}

La implementación anterior ahora se puede usar para simular un diccionario como:

var dict = new JSdict();

dict.add(1, "one")

dict.add(1, "one more")
"Duplicate keys not allowed!"

dict.getVal(1)
"one"

dict.update(1, "onne")

dict.getVal(1)
"onne"

dict.remove(1)

dict.getVal(1)
"Key not found!"

Esta es solo una simulación básica. Se puede optimizar aún más implementando un mejor algoritmo de tiempo de ejecución para trabajar en al menos O (nlogn) complejidad de tiempo o incluso menos. Como fusión / clasificación rápida en matrices y luego algunas búsquedas B para búsquedas. No probé ni busqué sobre el mapeo de una función hash en JS.

Además, la clave y el valor del objeto JSdict se pueden convertir en variables privadas para ser engañosas.

¡Espero que esto ayude!

EDITAR >> Después de implementar lo anterior, personalmente utilicé los objetos JS como matrices asociativas que están disponibles de fábrica.

sin embargo , me gustaría hacer una mención especial sobre dos métodos que en realidad resultaron útiles para convertirlo en una práctica experiencia de tabla hash.

Viz: dict.hasOwnProperty (clave) y eliminar dict [clave]

Lea esta publicación como un buen recurso sobre esta implementación / uso. Crear claves dinámicamente en una matriz asociativa de JavaScript

¡Gracias!

Vaibhav
fuente
5

Utilice objetos JavaScript. Puede acceder a sus propiedades como claves en un diccionario. Esta es la base de JSON. La sintaxis es similar a la de los diccionarios de Python. Ver: JSON.org

Adán
fuente
4

Una vieja pregunta, pero recientemente necesitaba hacer un puerto AS3> JS, y en aras de la velocidad escribí un objeto Diccionario simple estilo AS3 para JS:

http://jsfiddle.net/MickMalone1983/VEpFf/2/

Si no lo sabía, el diccionario AS3 le permite usar cualquier objeto como clave, en lugar de solo cadenas. Son muy útiles una vez que les ha encontrado un uso.

No es tan rápido como lo sería un objeto nativo, pero no he encontrado ningún problema significativo en ese sentido.

API:

//Constructor
var dict = new Dict(overwrite:Boolean);

//If overwrite, allows over-writing of duplicate keys,
//otherwise, will not add duplicate keys to dictionary.

dict.put(key, value);//Add a pair
dict.get(key);//Get value from key
dict.remove(key);//Remove pair by key
dict.clearAll(value);//Remove all pairs with this value
dict.iterate(function(key, value){//Send all pairs as arguments to this function:
    console.log(key+' is key for '+value);
});


dict.get(key);//Get value from key
MickMalone 1983
fuente
1
¡Biblioteca agradable y útil! Agregué una función de obtención, que pensé que faltaba y solucioné algunos problemas menores de sintaxis (falta el punto y coma, etc.). Aquí está el violín modificado: Diccionario en JSFiddle
Matt
Buen trabajo compañero, ¡no sé por qué no estaba ahí!
MickMalone1983
2

Firefox 13+ proporciona una implementación experimental del mapobjeto similar al dictobjeto en Python. Especificaciones aquí .

Solo está disponible en Firefox, pero se ve mejor que usar atributos de new Object(). Cita de la documentación:

  • Un Objeto tiene un prototipo, por lo que hay claves predeterminadas en el mapa. Sin embargo, esto se puede omitir usandomap = Object.create(null) .
  • Las claves de un Objectson Strings, donde pueden tener cualquier valor para unMap .
  • Puede obtener el tamaño de un Maparchivo fácilmente mientras tiene que realizar un seguimiento manual del tamaño de un archivo Object.
mquandalle
fuente