JavaScript中的有序散列
JavaScript对象没有存储属性的顺序(根据规范)。在循环中为…使用JavaScript中的有序散列,javascript,Javascript,JavaScript对象没有存储属性的顺序(根据规范)。在循环中为…使用时,Firefox似乎保留了属性定义的顺序。这种行为是我可以信赖的吗?如果没有,是否有一段JavaScript代码实现了有序散列类型?没有,因为,您不能依赖它。(或者:您只能依赖于对象是无序的属性集合。) 如果你想拥有一个有序散列集,你需要自己实现它。我做的一个技巧是将数据存储在一个常规无序散列中,然后将首选顺序存储在一个数组中。在JS中,您甚至可以将order数组作为哈希本身的一部分 var myHash = { a:
时,Firefox似乎保留了属性定义的顺序。这种行为是我可以信赖的吗?如果没有,是否有一段JavaScript代码实现了有序散列类型?没有,因为,您不能依赖它。(或者:您只能依赖于对象是无序的属性集合。)
如果你想拥有一个有序散列集,你需要自己实现它。我做的一个技巧是将数据存储在一个常规无序散列中,然后将首选顺序存储在一个数组中。在JS中,您甚至可以将order数组作为哈希本身的一部分
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)
var myHash={
a:“2”,
b:“3”,
c:“1”
};
myHash.order=[myHash.c,myHash.a,myHash.b];
警报(“我可以通过键访问值。这里是B:“+myHash.B”);
var message=“我还可以按以下顺序访问值:”;
对于(var i=0;i这个问题作为顶级搜索结果出现。在没有找到有序散列后,我只编写了这个小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
意识到时间很晚了,但我需要这个,在别处找不到。
*更新
添加了必要的不可枚举方法和属性。
快速实施ES 5(根据需要使用polyfill):
函数orderedHash(对象){
“严格使用”
var obj=对象| |{}
对象。定义属性(此{
“长度”:{
值:0,
可写:对
},
“钥匙”:{
值:[],
可写:对
},
“分类依据”:{
值:“”,
可写:对
}
})
this.hash(obj)
obj=null
}
Object.defineProperties(orderedHash.prototype{
“卑鄙小人”:{
值:函数sortByKeys(){
变量i,len,name
this.keys.sort(函数(a,b){
返回a>=b?1:-1
})
对于(i=0,len=this.keys.length;i=b?1:-1
})
newIndex=ordered.lastIndexOf(此[i])
名称=名称[i]
this.keys.splice(newIndex,0,name)
}
对于(i=0,len=ordered.length;i=b?1:-1
})
对于(i=0,len=this.length;i=索引){
这个[i]=这个[i+1]
}
}
删除此[this.length-1]
这个长度-=1
返回空
}
},
“toString”:{
值:函数toString(){
变量i,len,string=“”
对于(i=0,len=this.length;i
这里发生的事情是,通过使用Object.defineProperty()
而不是赋值,我们可以使属性不可枚举,因此当我们使用for…in
或Object.keys()
对哈希进行迭代时,我们只会得到有序值,但如果我们选中hash.propertyname
,它就会出现。
提供了插入、删除、同化其他对象的方法(hash()function orderedHash(object) {
'use strict'
var obj = object || {}
Object.defineProperties(this, {
'length': {
value: 0,
writable: true
},
'keys' : {
value: [],
writable: true
},
'sortedBy': {
value: '',
writable: true
}
})
this.hash(obj)
obj = null
}
Object.defineProperties(orderedHash.prototype, {
'sortByKeys': {
value: function sortByKeys() {
var i, len, name
this.keys.sort(function(a, b) {
return a >= b ? 1 : -1
})
for (i=0, len = this.keys.length; i < len; ++i) {
name = this.keys[i]
this[i] = this[name]
}
this.sortedBy = 'keys'
return null
}
},
'sortByValues': {
value: function sortByValues() {
var i, len, newIndex, name, ordered = [], names = this.keys.splice(0)
this.keys = []
for (i=0, len = this.length; i < len; ++i) {
ordered.push(this[i])
ordered.sort(function(a, b) {
return a >= b ? 1 : -1
})
newIndex = ordered.lastIndexOf(this[i])
name = names[i]
this.keys.splice(newIndex, 0 , name)
}
for (i=0, len = ordered.length; i < len; ++i) {
this[i] = ordered[i]
}
this.sortedBy = 'values'
return null
}
},
'insert': {
value: function insert(name, val) {
this[this.length] = val
this.length += 1
this.keys.push(name)
Object.defineProperty(this, name, {
value: val,
writable: true,
configurable: true
})
if (this.sortedBy == 'keys') {
this.sortByKeys()
} else {
this.sortByValues()
}
return null
}
},
'remove': {
value: function remove(name) {
var keys, index, i, len
delete this[name]
index = this.keys[name]
this.keys.splice(index, 1)
keys = Object.keys(this)
keys.sort(function(a, b) {
return a >= b ? 1 : -1
})
for (i=0, len = this.length; i < len; ++i) {
if (i >= index) {
this[i] = this[i + 1]
}
}
delete this[this.length - 1]
this.length -= 1
return null
}
},
'toString': {
value: function toString() {
var i, len, string = ""
for (i=0, len = this.length; i < len; ++i) {
string += this.keys[i]
string += ':'
string += this[i].toString()
if (!(i == len - 1)) {
string += ', '
}
}
return string
}
},
'toArray': {
value: function toArray() {
var i, len, arr = []
for (i=0, len = this.length; i < len; ++i) {
arr.push(this[i])
}
return arr
}
},
'getKeys': {
value: function getKeys() {
return this.keys.splice(0)
}
},
'hash': {
value: function hash(obj) {
var i, len, keys, name, val
keys = Object.keys(obj)
for (i=0, len = keys.length; i < len; ++i) {
name = keys[i]
val = obj[name]
this[this.length] = val
this.length += 1
this.keys.push(name)
Object.defineProperty(this, name, {
value: val,
writable: true,
configurable: true
})
}
if (this.sortedBy == 'keys') {
this.sortByKeys()
} else {
this.sortByValues()
}
return null
}
}
})
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();
var order=[];
var hash={"h1":4,"h2":2,"h3":3,"h4":1};
function cmp(a,b) {
if (hash[a] < hash[b]) return -1;
if (hash[a] > hash[b]) return 1;
return 0;
}
// Add initial hash object to order array
for(i in hash) order.push(i);
order.sort(cmp);
// h4:1 h2:2 h3:3 h1:4
// Add entry
hash['h5']=2.5;
order.push('h5');
order.sort(cmp);
// h4:1 h2:2 h5:2.5 h3:3 h1:4
// Delete entry
order.splice(order.indexOf('h5'), 1);
delete hash['h5'];
// h4:1 h2:2 h3:3 h1:4
// Display ordered hash array (with keys)
for(i in order) console.log(order[i],hash[order[i]]);
var obj ={ }
var order = [];
function add(key, value) {
obj[key] = value;
order.push(key);
}
function getOldestKey() {
var key = order.shift();
return obj[key]
}
function getNewsetKey() {
var key = order.pop();
return obj[key]
}
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 ]
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);
}
class @OrderedHash
constructor: (h_as_array=[])->
@keys = []
@vals = {}
if h_as_array.length > 0
i = 0
while i < h_as_array.length
@push(h_as_array[i], h_as_array[i+1])
i += 2
@
push: (k,v)->
@keys.push k if not @vals[k]
@vals[k] = v
length: ()-> return @keys.length
keys: ()-> return @keys
val: (k)-> return @vals[k]
vals: ()-> return @vals
each: (callback)->
return unless callback
for k in @keys
callback(@vals[k])