0

Note the code below shows the array in the console, not in the snippet output

var nodes = ["maria", "mary", "marks", "michael"];

function insert_word(split_nodes) {
  var rest = [];
  for (var i = 0; i < split_nodes.length; i++) {
    //console.log(current);
    var word = split_nodes[i];
    var letters = word.split("");
    var current = rest;
    console.log(current);
    for (var j = 0; j < letters.length; j++) {
      var character = letters[j];
      var position = current[character];
      if (position == null) {
        current = current[character] = j == letters.length - 1 ? 0 : {};
      } else {
        current = current[character];
      }
    }
  }
}
insert_word(nodes);

Above outputs this

M :{a : {r :{i :{a :0},
    k :0,   
    y :
    },
},
    i :{c :{h :{a :{e :{l :0}}}}}}}

but I want to output this :

M :{ar:{ia:0,
    k :0,   
    y :0
    },
 ichael :0
}

can anyone help me to find out this output from my code? how could i make suffeix from this code?

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
rai
  • 27
  • 1
  • 7

1 Answers1

0

This solution take a sightly changed object structure for the end indicator with a property isWord, because the original structure does not reflect entries like 'marc' and 'marcus', because if only 'marc' is uses, a zero at the end of the tree denotes the end of the word, but it does not allowes to add a substring, because the property is a primitive and not an object.

Basically this solution creates first a comlete tree with single letters and then joins all properties which have only one children object.

function join(tree) {
    Object.keys(tree).forEach(key => {
        var object = tree[key],
            subKeys = Object.keys(object),
            joinedKey = key,
            found = false;    

        if (key === 'isWord') {
            return;
        }
        while (subKeys.length === 1 && subKeys[0] !== 'isWord') {
            joinedKey += subKeys[0];
            object = object[subKeys[0]];
            subKeys = Object.keys(object);
            found = true;
        }
        if (found) {
            delete tree[key];
            tree[joinedKey] = object;
        }
        join(tree[joinedKey]);
    });
}

var node = ["maria", "mary", "marks", "michael"],
    tree = {};

node.forEach(string => [...string].reduce((t, c) => t[c] = t[c] || {}, tree).isWord = true);
console.log(tree);

join(tree);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

A recursive single pass approach with a function for inserting a word into a tree which updates the nodes.

It works by

  • Checking the given string with all keys of the object and if string start with the actual key, then a recursive call with the part string and the nested part of the trie is made.

  • Otherwise, it checks how many characters are the same from the key and the string.

    Then it checks the counter and creates a new node with the common part and two nodes, the old node content and a new node for the string.

    Because of the new node, the old node is not more necessary and gets deleted, as well as the iteration stops by returning true for the update check.

  • If no update took place, a new property with string as key and zero as value is assigned.

function insertWord(tree, string) {
    var keys = Object.keys(tree),
        updated = keys.some(function (k) {
            var i = 0;

            if (string.startsWith(k)) {
                insertWord(tree[k], string.slice(k.length));
                return true;
            }
            while (k[i] === string[i] && i < k.length) {
                i++;
            }
            if (i) {
                tree[k.slice(0, i)] = { [k.slice(i)]: tree[k], [string.slice(i)]: 0 };
                delete tree[k];
                return true;
            }
        });

    if (!updated) {            
        tree[string] = 0;
    }
}

var words = ["maria", "mary", "marks", "michael"],
    tree = {};

words.forEach(insertWord.bind(null, tree));
console.log(tree);

insertWord(tree, 'mara');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • you did a great job for me. can you help me one more? i want my output as like which i added into my question. it will dynamically change. – rai Feb 03 '18 at 17:51
  • the dynamic change is much more complex as it look like. actually i have no idea how to tackle that. – Nina Scholz Feb 03 '18 at 17:52
  • than i just only need the out put as like that. can i contact with you? M :{ar:{ia:0, k :0, y :0 }, ichael :0 } – rai Feb 03 '18 at 17:56
  • @Hey Nina Scholz God of javascript, how can i use keyup function for this function to retrieve the value? if i press "m" all the values of "m" will show and if i press "s" all the values of "s" will show below. Thanks – rai Feb 13 '18 at 06:12
  • @rai, that is a completely different question, you may ask. – Nina Scholz Feb 13 '18 at 07:24
  • i asked but no one reply or help me to findout the result. Thanks – rai Feb 13 '18 at 07:35