我正在尝试在Javascript中实现一个Trie,这很容易,但我似乎已经用我的对象遇到了障碍。
节点的结构如下:
var node = {
children: []
}
Children是一个由字符串中的字母映射的节点数组。所以字符串“Test”看起来像这样:
root = {
children: [
't' => {
children: [
'e' => {
children: [
's' => {
children: [
't' => {
children: []
}
]
}
]
}
]
}
]
};
因此每个children数组的长度应为1,但如果执行类似alert(this._root.children.length);
的操作,则会得到零。有关为何发生这种情况的任何想法?
以下是我实施的其余部分:
function Trie() {
this._root = {
children: []
};
}
Trie.prototype = {
//restore constructor
constructor: Trie,
add: function (str){
var curr = this._root,
prev,
currchar;
// For each character in the string
for(var i = 0, j = str.length; i < j; i++) {
// Insert only lowercase letters for efficiency
currchar = str.toLowerCase().charAt(i);
prev = curr;
curr = prev.children[currchar];
// Traverse until we hit a non-existant node
if(typeof(curr) == "undefined") {
// Make a new node
prev.children[currchar] = {
children: []
};
curr = prev.children[currchar];
}
}
}
答案 0 :(得分:2)
您正在向数组实例对象添加属性,而不是向数组添加元素。 length
属性仅包含数组元素,而不包括数组实例对象上的属性。
var a = [23, 42];
console.log(a.length); // 2
a['foo'] = 'bar';
console.log(a.length); // 2
a[2] = 1337;
console.log(a.length); // 3
<强>编辑:强> 您可以改为构造节点,如下所示:
var node = {
children: {},
length: function () {
var i = 0;
var k;
for (k in this.children) {
if (this.children.hasOwnProperty(k)) {
i++;
}
}
return i;
}
};
当然这是低效的。您应该在其原型上使用length方法定义一个Node类。或者,定义更新length属性的add
方法。
答案 1 :(得分:2)
我认为问题在于您使用javasrcipt数组作为关联数组(在其他语言中可以找到)。在javascript中,“associative”数组是没有length属性的对象。普通数组有数字索引。
与问题无关,但您可能会发现this有用。
答案 2 :(得分:-1)
也许你想要
str.toLowerCase().charCodeAt(i)
而不是
str.toLowerCase().charAt(i)
如果str
为"f1"
,则您要添加到子数组的属性为"f"
和"1"
,这会导致数组中包含名为{{1}的属性}和长度0,以及另一个长度为f
且属性为2
的子数组。
要仅获取数字属性,应确保属性名称是有效的数组索引 - 正整数可用31位表示。
使用1
代替charCodeAt
,您将获得属性名称charCode
和102
,而不是49
和"f"
。< / p>