Javascript javascript中的一组对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5657219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set of objects in javascript
提问by AshleysBrain
I'd like to have a set of objects in Javascript. That is, a data structure that contains only unique objects.
我想在 Javascript 中有一组对象。即,仅包含唯一对象的数据结构。
Normally using properties is recommended, e.g. myset["key"] = true
. However, I need the keys to be objects. I've read that Javascript casts property names to strings, so I guess I can't use myset[myobject] = true
.
通常建议使用属性,例如myset["key"] = true
. 但是,我需要将键作为对象。我读过 Javascript 将属性名称转换为字符串,所以我想我不能使用myset[myobject] = true
.
I could use an array, but I need something better than O(n) performance for adding, finding and removing items.
我可以使用数组,但我需要比 O(n) 性能更好的东西来添加、查找和删除项目。
It needs to be able to tell objects apart by reference only, so given:
它需要能够仅通过引用区分对象,因此给出:
var a = {};
var b = {};
then both a
and b
should be able to be added, because they're separate objects.
那么两者a
和b
应该都可以添加,因为它们是单独的对象。
Basically, I'm after something like C++'s std::set
, that can store Javascript objects. Any ideas?
基本上,我在追求像 C++ 那样的东西std::set
,它可以存储 Javascript 对象。有任何想法吗?
采纳答案by Ry-
回答by Jim Blackler
Here's a mad suggestion ... key it on the result of JSON.stringify(object)
这是一个疯狂的建议... JSON.stringify(object)
回答by Mark Kahn
It's not possible for all objects, but if your object has a .toString()
method implemented, it is:
并非所有对象都可以,但如果您的对象.toString()
实现了一个方法,则为:
var x = {toString: function(){ return 'foo'; }};
var y = {toString: function(){ return 'bar'; }};
var obj = {};
obj[x] = 'X';
obj[y] = 'Y';
console.log(obj);
// { foo: 'X', bar: 'Y' }
If you want to make this easier, make it a class:
如果你想让这更容易,把它变成一个类:
function myObj(name){
this.name = name;
}
myObj.prototype.toString = function(){ return this.name; }
var obj = {};
obj[new myObj('foo')] = 'X';
obj[new myObj('bar')] = 'Y';
回答by AshleysBrain
I'm answering my own question, but I came up with an alternative solution I thought was interesting and thought it would be useful to share it.
我正在回答我自己的问题,但我想出了一个我认为很有趣的替代解决方案,并认为分享它会很有用。
cwolves' answer gave me an idea. Providing an object's toString()
method uniquely identifies the instance, properties of an object can be used to store a set of objects. Essentially, to store object x
, you can use items[x.toString()] = x;
. Note that the value is the object itself, so then the set of objects can be extracted by looking at all item
's properties and dumping all the values in to an array.
狼队的回答给了我一个想法。提供对象的toString()
方法唯一标识实例,对象的属性可用于存储一组对象。本质上,要存储 object x
,您可以使用items[x.toString()] = x;
. 请注意,值是对象本身,因此可以通过查看 allitem
的属性并将所有值转储到数组中来提取对象集。
Here's the class, which I call ObjectSet
, in full. It requires objects are uniquely identified by their toString()
method, which is OK for my purposes. add
, remove
and contains
should all run in better than O(n) time - whatever javascript's property access efficiency is, which hopefully is either O(1) or O(n log n).
这是我称之为ObjectSet
的完整课程。它要求对象由它们的toString()
方法唯一标识,这对我来说是可以的。 add
,remove
并且contains
都应该比 O(n) 时间运行得更好 - 无论 javascript 的属性访问效率是多少,希望是 O(1) 或 O(n log n)。
// Set of objects. Requires a .toString() overload to distinguish objects.
var ObjectSet = function ()
{
this.items = {};
this.item_count = 0;
};
ObjectSet.prototype.contains = function (x)
{
return this.items.hasOwnProperty(x.toString());
};
ObjectSet.prototype.add = function (x)
{
if (!this.contains(x))
{
this.items[x.toString()] = x;
this.item_count++;
}
return this;
};
ObjectSet.prototype.remove = function (x)
{
if (this.contains(x))
{
delete this.items[x.toString()];
this.item_count--;
}
return this;
};
ObjectSet.prototype.clear = function ()
{
this.items = {};
this.item_count = 0;
return this;
};
ObjectSet.prototype.isEmpty = function ()
{
return this.item_count === 0;
};
ObjectSet.prototype.count = function ()
{
return this.item_count;
};
ObjectSet.prototype.values = function ()
{
var i, ret = [];
for (i in this.items)
{
if (this.items.hasOwnProperty(i))
ret.push(this.items[i]);
}
return ret;
};
回答by Vivin Paliath
For what you're trying to do (sets of objects), there is no native Javascript implementation. You would have to implement this on your own. One way to do this would be to implement a hashing function for your objects. The backing data-type of the set would be an associative array, where the key of the array is the value you get from calling the object's hash function, and the value of the array is the object itself.
对于您要执行的操作(对象集),没有本机 Javascript 实现。你必须自己实现这个。一种方法是为您的对象实现散列函数。集合的后备数据类型将是关联数组,其中数组的键是您从调用对象的哈希函数中获得的值,数组的值是对象本身。
Of course, this doesn't address the issue that you highlighted, so you will need to take equality into account as well (implement an equals function perhaps)?
当然,这并没有解决您强调的问题,因此您还需要考虑平等(也许实施 equals 函数)?
Instead of making the hash function a property of the object itself, you can have a standalone hash function that takes in an object as input and generates a hash value (presumably by iterating over its properties).
您可以拥有一个独立的哈希函数,将对象作为输入并生成哈希值(大概是通过迭代其属性),而不是让哈希函数成为对象本身的属性。
Using this method you should be able to get O(1)
for insertion, searching, and removing (not counting the order of the hash function, which shouldn't be any worse than O(n)
, especially if you are iterating over its properties to create your hashed value).
使用此方法,您应该能够获取O(1)
插入、搜索和删除(不计算散列函数的顺序,它不应该比 更糟O(n)
,尤其是当您迭代其属性以创建散列值时)。
回答by Sophistifunk
Just typed this up, it's only briefly tested:
刚刚输入这个,它只是简单地测试:
var Set = function Set()
{
var list = [];
var contains;
this.contains = contains = function(x) {
return list.indexOf(x) >= 0;
}
var put;
this.put = put = function(x) {
if (!contains(x))
list.push(x);
return this;
}
var remove;
this.remove = remove = function(x)
{
var idx = list.indexOf(x);
if (idx >= 0)
list.splice(idx,1);
return this;
}
var all;
this.all = all = function()
{
return list.concat();
}
return this;
}
回答by Aurelien
It seems that the inner call of function works when prefixed with this. Exemple:
当以this为前缀时,函数的内部调用似乎有效。例子:
var put;
this.put = put = function(x) {
if (!this.contains(x))
list.push(x);
return this;
}