JavaScript中的有序哈希

hek*_*ran 30 javascript

JavaScript对象没有为属性存储订单(根据规范).Firefox似乎在使用for...in循环时保留属性定义的顺序.这种行为是我可以依赖的吗?如果没有,那么在某处实现有序哈希类型的JavaScript代码?

Ond*_*žka 31

2016年的JavaScript,特别是EcmaScript 6,支持Map内置类.

Map对象按插入顺序迭代其元素 - for循环返回每个迭代的[key,value]数组.

这就是你所需要的.(我想知道为什么这是这个数据结构描述中的第一个信息.)

例如,

m = new Map()

m.set(3,'three')
m.set(1,'one')
m.set(2,'two')

m // Map { 3 => 'three', 1 => 'one', 2 => 'two' }

[...m.keys()] // [ 3, 1, 2 ]
Run Code Online (Sandbox Code Playgroud)

或者来自文档的示例:

var myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');

myMap // Map { 0 => 'zero', 1 => 'one' }

for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}

for (var key of myMap.keys()) {
  console.log(key);
}

for (var value of myMap.values()) {
  console.log(value);
}

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
Run Code Online (Sandbox Code Playgroud)

  • 重要脚注 - “请注意,在 ECMAScript 2015 规范中,对象确实保留了字符串和符号键的创建顺序,因此遍历仅具有字符串键的对象将按照插入顺序生成键” (3认同)

Gum*_*mbo 25

不,因为Object类型被指定为无序的属性集合,所以您不能依赖它.(或者:你只能依赖于一个对象是一个无序的属性集合.)

如果您想要一个有序的哈希集,您需要自己实现它.

  • Downvoting因为这只回答了问题的第一部分,并没有尝试解决方案 (5认同)
  • 投反对票,因为很明显海报知道这一点。不然他也不会问这个问题。 (3认同)

Flo*_*ann 21

@Vardhan在纯JavaScript中的回答,使用闭包而不是经典的OO并添加insert()方法:

function makeOrderedHash() {
    var keys = [];
    var vals = {};
    return {
        push: function(k,v) {
            if (!vals[k]) keys.push(k);
            vals[k] = v;
        },
        insert: function(pos,k,v) {
            if (!vals[k]) {
                keys.splice(pos,0,k);
                vals[k] = v;
            }
        },
        val: function(k) {return vals[k]},
        length: function(){return keys.length},
        keys: function(){return keys},
        values: function(){return vals}
    };
};

var myHash = makeOrderedHash();
Run Code Online (Sandbox Code Playgroud)


vrd*_*dhn 8

这个问题是最热门的搜索结果.在没有找到有序哈希之后,我只是写了这个小小的coffescript.希望这将有助于人们登陆此页面:

## OrderedHash
# f = new OrderedHash
# f.push('a', 1)
# f.keys()
# 
class OrderedHash
 constructor: ->
   @m_keys = []
   @m_vals = {}

  push: (k,v) ->
    if not @m_vals[k]
      @m_keys.push k
    @m_vals[k] = v

  length: () -> return @m_keys.length

  keys: () -> return @m_keys

  val: (k) -> return @m_vals[k]
  vals: () -> return @m_vals
Run Code Online (Sandbox Code Playgroud)

  • OP在JavaScript中寻求解决方案 - >请参阅下面的我的端口 (9认同)

Cra*_*ker 6

我做的一个技巧是将数据存储在常规的无序散列中,然后将首选顺序存储在数组中.在JS中,您甚至可以使订单数组成为散列本身的一部分.

var myHash = {
  a: "2",
  b: "3",
  c: "1"
};

myHash.order = [ myHash.c, myHash.a, myHash.b ];

alert("I can access values by key. Here's B: " + myHash.b);
var message =  "I can access also loop over the values in order: ";

for (var i=0;i<myHash.order.length;i++)
{ 
  message = message + myHash.order[i] + ", ";
}

alert(message)
Run Code Online (Sandbox Code Playgroud)

它不是很优雅,但它完成了工作.

  • 该解决方案在我看来非常脆弱,因为用于订购的机制并未封装,并且客户端代码必须了解内部机制才能使其正常工作……对于一次性项目来说可能是可以的,但肯定不能用于生产的IMO。 (2认同)