y a-t-il des dictionnaires en javascript comme python?

99

j'ai besoin de faire un dictionnaire en javascript comme celui-ci

je ne me souviens pas de la notation exacte, mais c'était quelque chose comme:

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

existe-t-il une telle chose en javascript?

l --''''''--------- '' '' '' '' '' '
la source
2
Voir cette question: stackoverflow.com/questions/130543/…
Manoj Govindan
5
La réponse que vous avez acceptée est très fausse.
Esben Skov Pedersen
@EsbenSkovPedersen Quelles erreurs avez-vous remarquées dans cette réponse?
Anderson Green
Je vois qu'il est édité après avoir commenté. Il semble: manquait
Esben Skov Pedersen
2
Lire la réponse la plus récente pour ES6 Maps stackoverflow.com/a/32993723/1993919 (commentant pour la même raison qu'elle a été publiée)
Old Badman Gray

Réponses:

130

C'est un ancien article, mais j'ai pensé que je devrais quand même fournir une réponse illustrée.

Utilisez la notation d'objet de javascript. Ainsi:

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

Et pour accéder aux valeurs:

states_dictionary.AK[0] //which is liza

ou vous pouvez utiliser la notation d'objet littérale javascript, dans laquelle les clés ne doivent pas être entre guillemets:

states_dictionary={ 
     CT:["alex","harry"], 
     AK:["liza","alex"], 
     TX:["fred", "harry"]
};
Chef
la source
11
il est à noter que le premier exemple devrait produire le même objet dans les deux langues en utilisant exactement la même syntaxe sauf la fermeture ';'. states_dictionary = {"CT": ["alex", "harry"], "AK": ["liza", "alex"], "TX": ["fred", "harry"]}
Denis C
Je suis plus habitué à la notation littérale des objets, puisque vous y accédez de la même manière quelle est la différence entre les deux?
John Demetriou
2
@JohnDemetriou la principale différence est que les clés de notation d'objet javascript doivent être des chaînes (entre guillemets ""). La notation objet est comme vue dans JSON pour l'interchage de données et a été inspirée par la notation objet littérale; il est à noter que JSON est généralement utilisé dans un contexte de chaîne
Chief
2
En fait, Python autorise les points-virgules de fin d'instruction, donc le premier exemple est complètement valide à la fois en Python et en JavaScript
celticminstrel
Si la valeur provient de l'utilisateur, il faut faire attention à l'utiliser Object.hasOwnProperty.call(dictionary, key)(sinon l'utilisateur peut entrer une valeur de valueOf et dictionary['valueOf']renvoie la Object.valueOf()fonction appartenant au prototype Object qui n'est probablement pas ce à quoi votre code s'attendrait - bug potentiel ou problème de sécurité ). Si la clé n'est pas de type chaîne, alors des précautions doivent être prises, sinon les conversions numériques implicites et toString vous poseront des problèmes. Le Maptype ES6 a été conçu pour fournir des fonctionnalités étendues aux dictionnaires.
robocat
49

Il n'y avait pas de véritables tableaux associatifs en Javascript jusqu'en 2015 (sortie d'ECMAScript 6). Depuis lors, vous pouvez utiliser l'objet Map comme états Robocat. Recherchez les détails dans MDN . Exemple:

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

Sans prise en charge d'ES6, vous pouvez essayer d'utiliser des objets:

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

Cependant, avec les objets, il n'est pas possible d'utiliser des propriétés ou des méthodes typiques de tableau comme array.length. Au moins, il est possible d'accéder au "object-array" dans une boucle for-in-loop.

Alex
la source
3
Et la performance? recherche une clé dans un objet à temps constant?
Saher Ahwal
5
Puisque o ["key"] est équivalent à o.key en Javascript, les performances sont presque les mêmes. Cependant, les performances dépendent du moteur Javascript / navigateur Web. Il existe de nombreuses différences entre ceux-ci, en particulier dans les anciennes versions.
Alex
ECMAScript 6 définit un objet Map officiel (ie "Il n'y a pas de véritables tableaux associatifs en Javascript" est maintenant incorrect).
robocat
18

Je me rends compte que c'est une vieille question, mais elle apparaît dans Google lorsque vous recherchez des `` dictionnaires javascript '', j'aimerais donc ajouter aux réponses ci-dessus que dans ECMAScript 6, l' Mapobjet officiel a été introduit, qui est un dictionnaire la mise en oeuvre:

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

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

Contrairement aux objets normaux de javascript, il autorise n'importe quel objet comme clé:

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
la source
Fonctionne pour moi, agréable d'utiliser une méthode ES6 plus propre. Je vous remercie! Suivi, connaissons-nous un moyen de "bulk set ()", par exemple comme python dict = { key: value)?
Joe Sadoski
10

J'ai créé un dictionnaire simple en JS ici:

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

L'implémentation ci-dessus peut maintenant être utilisée pour simuler un dictionnaire comme:

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

Ceci est juste une simulation de base. Il peut être encore optimisé en implémentant un meilleur algorithme de temps d'exécution pour fonctionner avec une complexité de temps au moins O (nlogn) ou même moins. Comme la fusion / tri rapide sur les tableaux, puis une recherche B pour les recherches. Je n'ai pas essayé ou cherché à mapper une fonction de hachage dans JS.

De plus, la clé et la valeur de l'objet JSdict peuvent être transformées en variables privées pour être sournoises.

J'espère que cela t'aides!

EDIT >> Après avoir implémenté ce qui précède, j'ai personnellement utilisé les objets JS en tant que tableaux associatifs disponibles prêts à l'emploi.

toutefois , je voudrais faire une mention spéciale sur deux méthodes qui se sont avérées utiles pour en faire une expérience de hachage pratique.

Viz: dict.hasOwnProperty (clé) et supprimer dict [clé]

Lisez cet article comme une bonne ressource sur cette implémentation / utilisation. Création dynamique de clés dans un tableau associatif JavaScript

Merci!

Vaibhav
la source
5

Utilisez des objets JavaScript. Vous pouvez accéder à leurs propriétés comme des clés dans un dictionnaire. C'est le fondement de JSON. La syntaxe est similaire aux dictionnaires Python. Voir: JSON.org

Adam
la source
4

Une vieille question mais j'ai récemment eu besoin de faire un port AS3> JS, et pour des raisons de vitesse, j'ai écrit un simple objet Dictionary de style AS3 pour JS:

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

Si vous ne le saviez pas, le dictionnaire AS3 vous permet d'utiliser n'importe quel objet comme clé, par opposition à de simples chaînes. Ils sont très utiles une fois que vous avez trouvé une utilisation pour eux.

Ce n'est pas aussi rapide qu'un objet natif le serait, mais je n'ai trouvé aucun problème significatif avec lui à cet égard.

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
MickMalone1983
la source
1
Bibliothèque agréable et utile! J'ai ajouté une fonction get, que je pensais manquante et j'ai corrigé quelques problèmes de syntaxe mineurs (point-virgule manquant, etc.). Voici le violon modifié: Dictionnaire dans JSFiddle
Matt
Bon boulot, je ne sais pas pourquoi ce n'était pas là!
MickMalone1983
2

Firefox 13+ fournit une implémentation expérimentale de l' mapobjet similaire à l' dictobjet en python. Spécifications ici .

Il n'est disponible que dans Firefox, mais il est meilleur que d'utiliser les attributs d'un new Object(). Citation de la documentation:

  • Un objet a un prototype, il y a donc des clés par défaut dans la carte. Cependant, cela peut être contourné en utilisantmap = Object.create(null) .
  • Les clés d'un Objectsont Strings, où elles peuvent être n'importe quelle valeur pour unMap .
  • Vous pouvez Mapfacilement obtenir la taille d'un tandis que vous devez suivre manuellement la taille d'un fichier Object.
mquandalle
la source