在我的项目中,我有一组对象(类实例),我需要按键访问,但也按给定的顺序排序和访问。我该如何存储这些物品?
我可以同时拥有数组和字典并手动使它们保持同步但这不是最理想的(例如,当你想要删除一个对象时,你需要首先在数组中找到它)。
//dictionary properties
objectsDictionary[object.id] = object;
//array properties
objectsArray.sort(function)
是否有一个数据结构结合了Array和Dictionary的属性?可以在不需要内部遍历阵列的情况下调制这种结构吗?
我正在使用的语言是TypeScript,但答案可能更为通用。
答案 0 :(得分:2)
您可以使用这样的构造函数自己实现。请注意,大多数方法必须在实例上定义,因为它们使用的是未共享的引用。
/* OADictionary
* value getItemAt , int index
* value getItem , str key
* void addItem , str key, value [, int index]
* void removeItemAt , int index
* void removeItem , str key
* void sort , function comparator(key_a, key_b, val_a, val_b)
*/
function OADictionary() {
var keys = [],
obj = {};
this.getItemAt = function (index) {
return obj[keys[index]];
};
this.getItem = function (key) {
return obj[key];
};
this.addItem = function (key, val, index) {
if (obj[key]) throw new Error('key already exists: ' + key);
obj[key] = val;
if (index || index === 0)
keys.splice(index, 0, key);
else
keys.push(key);
};
this.removeItemAt = function (index) {
delete obj[keys[index]];
keys.splice(index, 1);
};
this.removeItem = function (key) {
delete obj[key];
keys.splice(keys.indexOf(key), 1);
};
this.sort = function (comparator) {
var mComparator = function (key_a, key_b) {
return comparator(key_a, key_b, obj[key_a], obj[key_b]);
};
if (comparator)
keys.sort(mComparator);
else
keys.sort();
};
}
现在您可以创建有序的键值对
var d = new OADictionary();
d.addItem('foo', 'bar');
d.addItem('fizz', 'buzz');
d.getItem('fizz'); // "buzz"
d.getItemAt(0); // "bar"
d.sort();
d.getItemAt(0); // "buzz"
答案 1 :(得分:1)
通常在JavaScript中,您不能将任意索引与同一对象上的任何其他索引相结合,并获得可预测的结果。例如:
var arrayAndDictionary = /*... something ...*/;
// Accidently malicious user data
var objects = [{ id: 'sort' }, {id: 'length'}, {id: 'forEach' }];
objects.forEach(object => {
arrayAndDictionary[object.id] = object;
});
objects.sort(); // Crash.
真的,除非你100%控制那些id并且非常小心,否则你甚至不想关闭id。你可以被Little Bobby Proto烧掉:
// Collection of users on our website
var myObjects = {};
// New user named __proto__ signs up
myObjects['__proto__'] = { 'userId': 'bobby' }
// Is there a user named 'userId' ?
alert(myObjects['userId']); // "bobby", not undefined
答案 2 :(得分:1)