Массив внутри объекта, возвращающий длину 0, хотя присутствуют элементы - PullRequest
0 голосов
/ 15 июня 2011

Я пытаюсь реализовать Trie в Javascript, что достаточно просто, но я, кажется, столкнулся с дорожным блоком с моим объектом.

Узлы структурированы следующим образом:

var node = {
    children: []
}

Children - это массив узлов, который отображается буквой в строке.Таким образом, строка «Test» будет выглядеть следующим образом:

root = {
  children: [
      't' => {
          children: [
              'e' => {
                   children: [
                       's' => {
                            children: [
                                 't' => {
                                      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];
            }
        }
    }

Ответы [ 3 ]

2 голосов
/ 15 июня 2011

Вы добавляете свойства к объекту экземпляра массива, а не элементы к массиву. Свойство 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;
    }
};

Это, конечно, неэффективно. Вместо этого вы должны определить класс Node с помощью метода length для его прототипа. В качестве альтернативы, определите метод add, который обновляет свойство длины.

2 голосов
/ 15 июня 2011

Я думаю, что проблема в том, что вы используете массив javasrcipt в качестве ассоциативного массива (как в других языках).В javascript «ассоциативные» массивы - это объекты, которые не имеют свойства длины.Обычные массивы имеют числовые индексы.

Не имеет отношения к вопросу, но вы можете найти это полезным.

0 голосов
/ 15 июня 2011

Может быть, вы хотите

str.toLowerCase().charCodeAt(i)

вместо

str.toLowerCase().charAt(i)

Если str равно "f1", то свойства, которые вы добавляете в дочерний массив: "f" и "1", должны вызывать массив со свойством f и длиной 0, а другой дочерний массив с длина 2 и свойство 1.

Чтобы получить только числовые свойства, вы должны убедиться, что имена ваших свойств являются действительными индексами массива - положительными целыми числами, представленными в 31 бите.

Используя charCodeAt вместо charCode, вы получите имена свойств 102 и 49 вместо "f" и 1.

...