排序地图实施

时间:2013-02-01 11:11:18

标签: javascript jquery map underscore.js sortedmap

我的任务

在我的JavaScript代码中,我经常使用对象将键“映射”到值,以便稍后可以通过某个值直接访问它们。例如:

var helloMap = {};
helloMap.de = "Hallo";
helloMap["en"] = "Hello";
helloMap.es = "Hola";

所以我使用两个可用符号 object style array style 在源代码中逐步构建地图对象。

稍后我可以访问我通过helloMap["de"]添加的值。如果我不必关心在对象上设置属性的顺序,那就没关系了。

如果我想现在迭代对象属性,据我所知,没有办法确保我按照它们被添加的顺序迭代它们。

注意:我不能使用一些包装器对象,只需在其中保存一个数组,然后使用其方法添加值,如下所示:

var HelloMap = function(){
  this.myMap = [];
  this.addProperty = function(key, value){
    this.myMap.push({key: key, value: value});
  }
}

或类似的东西对我不起作用。因此,解决方案需要对使用该对象的程序员绝对透明。

那就是说我需要的对象是一个空对象,它维护了添加到它的属性的顺序。这样的事情可以做到:

var helloMap = {};
helloMap = getOrderAwareObject(helloMap);

以便在“按顺序”对象中跟踪表单helloMap.xy = "foo"helloMap["yz"] = "bar"的每个进一步分配,

可能的解决方案

由于我没有在下划线或jQuery中找到任何解决方案给我这样一个特殊的对象,因此我遇到了使用Object.defineProperty为JavaScript对象定义属性的getter和setter的可能性,因为我可以依赖 ECMAScript 5 标准我可以使用它。

这个问题是,在实际设置之前,您必须知道可以在对象上设置的所有可能属性。因为如果您定义它,您必须命名它。

我正在搜索的内容类似于默认抓取器默认设置器,如果没有为该属性定义了getter和setter,它将应用于该对象。所以我可以隐藏对象界面后面的有序地图

  • 您知道的任何框架中是否已有解决方案?
  • 是否有类似“默认getter / setter”的机制?

5 个答案:

答案 0 :(得分:6)

我担心你需要一个内部使用数组的包装器。 ECMAScript 5(这是当前浏览器JavaScript实现所基于的标准)根本不允许有序对象属性。

但是,ECMAScript 6将具有已订购属性的Map implementation。另请参阅http://www.nczonline.net/blog/2012/10/09/ecmascript-6-collections-part-2-maps/

ECMAScript 6中可能还有其他选项。请参阅以下问题:

How can I define a default getter and setter using ECMAScript 5?

答案 1 :(得分:4)

添加指向自定义javascript库的链接,该库提供排序映射和其他实现,以供将来在此线程中引用。查看https://github.com/monmohan/dsjslib -msingh

答案 2 :(得分:3)

我不知道一般解决方案,但非一般解决方案构建起来非常简单。

通常,您维护一个对象Array,其中几个方法被定义为Array的属性。至少,那是我的方法。

以下是一个示例,来自较大的应用程序(以修改的形式):

var srcs = [];
srcs.find = function(dist) {
    var i;
    for(i=0; i<this.length; i++) {
        if(dist <= this[i].dist) { return this[i]; }
    }
    return null;
};
srcs.add = function(dist, src) {
    this.push({ dist:dist, src:src });
}
srcs.remove = function(dist) {
    var i;
    for(i=0; i<this.length; i++) {
        if(this[i].dist === dist) {
            srcs.splice(i,1);
            return true;
        }
    }
    return false;
};
srcs.add(-1, 'item_0.gif' );
srcs.add(1.7, 'item_1.gif');
srcs.add(5, 'item_2.gif');
srcs.add(15, 'item_3.gif');
srcs.add(90, 'item_4.gif');

不幸的是,你失去了普通js对象查找的简单性,但这是你为拥有一个有序实体付出的代价。

如果你绝对必须有order和dot.notation,那么维护一个普通的js Object用于查找一个数组用于命令。小心翼翼地保持这两者的完整性。

答案 3 :(得分:0)

请参阅我对this问题的回答。我实现了一个基本的有序哈希表(仅限ES 5+,没有打扰到polyfill)

答案 4 :(得分:-1)

var put = function(k,v){
 if(map[k]){
   console.log("Key "+ k+" is already present");
 }else
 {
   var newMap = {};
   map[k] = v;
   Object.keys(map).sort().forEach(function(key){
   newMap[key] = map[key];
 });
   map = newMap;
   //delete newMap; in case object memory need to release
   return map;
 }
}

Put方法将始终采用键值对,在内部创建具有实际地图中的排序键的另一个地图,更新值并使用已排序的键返回更新的地图。不需要包含外部库。