像python这样的javascript中有字典吗?


97

我需要像这样用javascript制作字典

我不记得确切的符号了,但是有点像:

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

javascript中有这样的事情吗?



5
您接受的答案是非常错误的。
Esben Skov Pedersen

@EsbenSkovPedersen您在该答案中注意到哪些错误?
安德森·格林

我评论后看到它已被编辑。似乎:失踪了
Esben Skov Pedersen

2
阅读有关ES6 Maps stackoverflow.com/a/32993723/1993919的最新答案(出于相同的原因进行评论)
Old Badman Gray

Answers:


128

这是一篇旧文章,但我认为无论如何我都应该提供一个图解的答案。

使用javascript的对象符号。像这样:

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

并访问值:

states_dictionary.AK[0] //which is liza

或者您可以使用javascript文字对象表示法,其中键不需要用引号引起来:

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

11
值得注意的是,第一个示例应该使用完全相同的语法在两种语言中产生相同的对象,除了结尾的';'。States_dictionary = {“ CT”:[“ alex”,“ harry”],“ AK”:[“ liza”,“ alex”],“ TX”:[“ fred”,“ harry”]}
Denis C

我更习惯文字对象表示法,因为您以相同的方式访问它们,两者之间有什么区别?
John Demetriou 2015年

2
@JohnDemetriou的主要区别是javascript对象符号键必须为字符串(用双引号“”括起来)。对象表示法就像在JSON中用于数据交换一样,它受到文字对象表示法的启发。值得注意的是,JSON通常在字符串上下文中使用
Chief

2
实际上,Python允许使用语句终止分号,因此第一个示例在Python和JavaScript中都完全有效
celticminstrel 2015年

如果值来自用户,则需要谨慎使用Object.hasOwnProperty.call(dictionary, key)(否则用户可以输入valueOf的值并dictionary['valueOf']返回Object.valueOf()属于对象原型的函数,这可能不是您的代码所期望的-潜在的错误或安全问题)。如果键不是字符串类型,则需要格外小心,否则隐式数字和toString转换将为您带来问题。ES6 Map类型旨在为词典提供扩展功能。
robocat

48

直到2015年(ECMAScript 6发行版),Javascript中都没有真正的关联数组。从那时起,您可以将Map对象用作Robocat状态。在MDN中查找详细信息。例:

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

如果不支持ES6,则可以尝试使用对象:

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

但是,对于对象,无法使用典型的数组属性或方法,例如array.length。至少可以在for-in-loop中访问“对象数组”。


3
表现如何呢?在对象恒定时间内查找键?
2011年

5
由于o [“ key”]与Java中的o.key等效,因此性能几乎相同。但是性能取决于Javascript Engine / Webbrowser。两者之间有很多差异,尤其是在旧版本中。
亚历克斯(Alex)

ECMAScript 6定义了一个正式的Map对象(即,“ Javascript中没有真正的关联数组”现在不正确)。
robocat

18

我意识到这是一个古老的问题,但是当您搜索“ javascript词典”时,它会在Google中弹出,因此我想在上述答案中加上ECMAScript 6中Map引入的官方对象,它是字典实施:

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

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

与javascript的普通对象不同,它允许任何对象作为键:

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({});

对我有用,很高兴使用更干净的ES6方法。谢谢!跟进,我们知道如何“批量set()”,例如python dict = { key: value)吗?
Joe Sadoski

10

在JS中创建了一个简单的字典:

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

上面的实现现在可以用于模拟字典,如下所示:

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

这只是一个基本的模拟。可以通过实施更好的运行时间算法以使其至少达到O(nlogn)时间复杂度甚至更低的复杂度来对其进行进一步优化。像对数组进行合并/快速排序,然后对查询进行一些B搜索。我没有尝试或搜索过有关在JS中映射哈希函数的信息。

另外,可以将JSdict obj的键和值转换为私有变量,以防止偷偷摸摸。

希望这可以帮助!

编辑>>完成上述操作后,我个人使用了JS对象作为现成可用的关联数组。

但是,我想特别提到两种方法,它们实际上被证明有助于使它成为方便的哈希表体验。

即:dict.hasOwnProperty(key) 删除dict [key]

阅读这篇文章,作为有关此实现/用法的好资源。 在JavaScript关联数组中动态创建键

谢谢!


5

使用JavaScript对象。您可以访问它们的属性,例如字典中的键。这是JSON的基础。语法类似于Python字典。请参阅:JSON.org


4

一个老问题,但是最近我需要做一个AS3> JS端口,为了提高速度,我为JS写了一个简单的AS3样式的Dictionary对象:

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

如果您不知道,AS3词典允许您使用任何对象作为键,而不仅仅是字符串。一旦您发现它们的用途,它们就会非常方便。

它的速度不如本地对象快,但是在这方面,我还没有发现任何重大问题。

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

1
尼斯和有用的图书馆!我添加了一个get函数,我认为该函数已丢失并修复了一些较小的语法问题(缺少分号等)。这是修改过的小提琴:JSFiddle中的字典
Matt

好伙伴,不知道为什么不在那里!
MickMalone1983年

2

Firefox 13+提供了map类似于dictpython中对象的实验性实现。规格在这里

它仅在firefox中可用,但看起来比使用a的属性更好new Object()。来自文档的引用:

  • 对象具有原型,因此地图中包含默认键。但是,可以使用绕过此操作map = Object.create(null)
  • 的键ObjectStrings,其中它们可以是的任何值Map
  • Map当您必须手动跟踪的大小时,您可以轻松获得大小Object
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.