有没有简单的一成不变的哈希和JavaScript的数组实现? 我不需要最好的速度,合理的速度比克隆更好的将是一件好事。
此外,如果在Java或可以容易理解和移植到JavaScript的一些其他语言简单的实现,这将是也好看。
更新:
我们的目标是不是只是冻结哈希(或数组),而是使更新操作的有效执行 - 不变的散列的更新应该返回一个不可改变的哈希值。 它应该是比“克隆原创和更新”这样做更有效。
本机JS类型有更新像O(1)复杂性,用克隆的复杂性将是O(n)的,具有特殊不可变的数据结构(我问),这将是0(的log(n))
UPDATE2:JavaScript的已经有数组/哈希:
是的,但它们是可变的,我需要类似,但一成不变的东西,基本上就可以非常简单地通过克隆完成hash2 = hash1.clone(); hash2[key] = value
hash2 = hash1.clone(); hash2[key] = value
但它是非常低效的,有使得它非常有效的算法,而无需使用clone
。
hash1 = {}
hash2 = hash1.set('key', 'value2')
hash3 = hash1.set('key', 'value3)
console.log(hash1) // => {}
console.log(hash2) // => {key: 'value2'}
console.log(hash3) // => {key: 'value3'}
解:
这不是不可改变的散列的实现,但更喜欢我现在的问题一个黑客,也许它也可以帮助别人。
多一点,为什么我需要一成不变的数据结构 - 我用的Node.js和排序的内存数据库。 一个请求可以读取数据库,等更新吧 - 更新过程可能需要大量的时间(调用远程服务) - 所以我不能阻止所有的阅读过程,并等待更新将完成,同时更新可能会失败,并且数据库应该回滚。 所以,我需要以某种方式隔离(ACID)读取和写入操作的内存数据库。
这就是为什么我需要一成不变的数组和哈希 - 实现排序MVCC的。 但似乎有一个更简单的方式来做到这一点。 而不是直接更新数据库 - 更新操作只是记录数据库更改的(但不直接执行它) - 在“添加42阵列db.someArray”的形式。
到底 - 更新操作的产品将是这种改变命令的阵列,因为它可以非常迅速地应用 - 我们可以阻止应用它的数据库。
但是,它仍然将是有趣的,看看是否有实现在JavaScript不可变的数据结构,所以我会离开这个问题打开。
我知道这个问题是旧的,但我认为人们正在寻找像我应该指出,Facebook的Immutable.js它提供了许多不同类型的不可变的数据结构的一个非常有效的方式。
我不得不为JS持久数据结构相同的要求,所以前一阵子我做了一个持续映射的实现.. https://github.com/josef-jelinek/cofy/blob/master/lang/feat.js
它包含实现平衡树基(排序)地图,以及一个天真的写入时复制地图(和未完成的持续矢量/阵列)。
var map = FEAT.map();
var map1 = map.assoc('key', 'value');
var value = map1.get('key');
var map2 = map1.dissoc('key');
...
它支持其他方法,如count()
contains(key)
, keys(into = [])
values(into = [])
toObject(into = {})
toString()
实施是不是太复杂,它是在公共领域。 我接受建议和贡献者太:)。
更新 :你可以找到单元测试(使用示例) https://github.com/josef-jelinek/cofy/blob/master/tests/test-feat.html
更新2:持久性矢量实施,现在有作为与以下操作: count()
get(i)
set(i, value)
, push(value)
, pop()
toArray(into = [])
toString()
使对象不可变的唯一方法是将其隐藏在函数内部。 然后,您可以使用该函数返回将默认散列或更新的版本,但你不能真正存储一个不可改变的哈希在全球范围内。
function my_hash(delta) {
var default = {mykey: myvalue};
if (delta) {
for (var key, value in delta) {
if (default.hasOwnProperty(key)) default[key] = value;
}
}
return default;
}
我不认为这是一个好主意,但。
克隆在Javascript对象我所知道的最好的方法,是包含在一个underscore.js
不久:
_.clone = function(obj) {
if (!_.isObject(obj)) return obj;
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
for (var prop in source) {
obj[prop] = source[prop];
}
});
return obj;
};