组合数组和字典属性的数据类型

时间:2014-03-19 16:22:07

标签: javascript arrays oop dictionary typescript

在我的项目中,我有一组对象(类实例),我需要按键访问,但也按给定的顺序排序和访问。我该如何存储这些物品?

我可以同时拥有数组和字典并手动使它们保持同步但这不是最理想的(例如,当你想要删除一个对象时,你需要首先在数组中找到它)。

//dictionary properties
objectsDictionary[object.id] = object;

//array properties 
objectsArray.sort(function)

是否有一个数据结构结合了Array和Dictionary的属性?可以在不需要内部遍历阵列的情况下调制这种结构吗?

我正在使用的语言是TypeScript,但答案可能更为通用。

3 个答案:

答案 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)

您可以尝试使用Map对象。

您可以通过密钥访问:

  

Map对象是一个简单的键/值映射

并按顺序迭代:

  

Map对象可以按插入顺序迭代其元素