public CustomTrie(TrieSettings <TK, TV, TI> settings) { _settings = settings; _root = _settings.TrieBuilder(); _needNormalizing = _settings.IndexBuilder.ShouldNormalize(); _maxLevel = settings.Level; }
/// <summary> /// Create an empty node with no children and null value /// </summary> /// <param name="parent">Parent node of this node</param> /// <param name="key">Key Bit</param> public TrieNode(ITrieNode <TKeyBit, TValue> parent, TKeyBit key) { this.KeyBit = key; this.Value = null; this.Parent = parent; this._children = new Dictionary <TKeyBit, ITrieNode <TKeyBit, TValue> >(); }
private int removeAux(string word, ITrieNode node) //TODO: FALTA PROBAR { if (word == "") { //Caso base recursivo if (!Convert.ToBoolean(node.isTerminated())) { return(0); } } else if (Convert.ToBoolean(node.isTerminated())) //TODO: Falta verificar que ya se haya revisado toda la palabra { return(0); } else { //Caso trivial removeAux(word.Substring(1), node.value(word[0])); } //Rollback if (node.getChildrenCount() < 2) { node.asign(word[0], null); return(1); } else { return(0); } }
public bool MoveNext() { if (myBFS.Count == 0) { return(false); } Current = null; if (myCurrentNodes != null) { lastCount++; if (myCurrentNodes.Count > lastCount) { Current = myCurrentNodes[lastCount]; } } while (myBFS.Count != 0 && Current == null) { ITrieNode <ArrayType, Item> Out = myBFS.Dequeue(); if (Out.HasTerminalNodes()) { myCurrentNodes = Out.GetTerminalItems(); lastCount = 0; Current = myCurrentNodes[lastCount]; } foreach (var A in Out.Children) { myBFS.Enqueue(A); } } return(Current != null); }
/// <summary> /// Tries to get the Value associated with a given Key /// </summary> /// <param name="key">Key</param> /// <param name="value">Value, will be null if the key does not exist or has no value associated with it</param> /// <returns>True if the Key exists in the Trie and has a value associated with it, False if it does not</returns> public bool TryGetValue(TKey key, out TValue value) { value = null; ITrieNode <TKeyBit, TValue> node = this._root; IEnumerable <TKeyBit> bs = this._keyMapper(key); foreach (TKeyBit b in bs) { //Bail out early if key does not exist if (!node.TryGetChild(b, out node)) { return(false); } } if (node.HasValue) { value = node.Value; return(true); } else { return(false); } }
/// <summary> /// Finds and returns a Node that has the shortest prefix match greater than or equal to the given Key using the given Key to Key Bit mapping function /// </summary> /// <param name="bs">Key Bits</param> /// <returns>Null if the Key does not map to a Node</returns> /// <remarks> /// The ability to provide a specific sequence of key bits may be useful for custom lookups where you don't necessarily have a value of the <strong>TKey</strong> type but do have values of the <strong>TKeyBit</strong> type /// </remarks> public ITrieNode <TKeyBit, TValue> FindSuccessor(IEnumerable <TKeyBit> bs) { ITrieNode <TKeyBit, TValue> node = this._root; foreach (TKeyBit b in bs) { //Bail out early if key does not exist if (!node.TryGetChild(b, out node)) { return(null); } } Queue <ITrieNode <TKeyBit, TValue> > depthFirstQueue = new Queue <ITrieNode <TKeyBit, TValue> >(); depthFirstQueue.Enqueue(node); while (depthFirstQueue.Count > 0) { node = depthFirstQueue.Dequeue(); if (node.HasValue) { return(node); } foreach (var child in node.Children.OrderBy(n => n.KeyBit, this.KeyBitComparer)) { depthFirstQueue.Enqueue(child); } } return(null); }
public void SetNode(ITrieNode <TK, TV> node) { if (node != null) { var realized = Cast(node); _nodes.AddOrUpdate(node.Id, realized, (k, v) => realized); } }
/// <summary> /// Creates a descendant nodes enumable /// </summary> /// <param name="node">Node</param> public DescendantNodesEnumerable(ITrieNode <TKeyBit, TValue> node) { if (node == null) { throw new ArgumentNullException("node"); } this._node = node; }
public void TrieContractFind1() { ITrie <String, char, String> trie = this.GetInstance(); ITrieNode <char, String> node = trie.Find("test"); Assert.IsNull(node); }
public void TrieContractMoveToNode1() { ITrie <String, char, String> trie = this.GetInstance(); ITrieNode <char, String> node = trie.MoveToNode("test"); Assert.IsNotNull(node); }
private void AddOrUpdateInternal(IEnumerable <TK> sequence, Func <ITrieNode <TK, TV>, ITrieNode <TK, TV> > modify) { modify = modify ?? (n => n); ITrieNode <TK, TV> node = null; long?nodeId = null; foreach (var v in sequence) { //clear any previously tracked node, its not a leaf if (node != null) { _memory.SetNode(node); node = null; } //get next level var childId = _memory.GetRelation(nodeId, v); //if level doesn't exist, add it if (childId == null) { node = _memory.NewNode(); _memory.SetRelation(nodeId, v, node.Id); //if new level had a parent try and alter parent with new key value if (nodeId.HasValue) { var parent = _memory.GetNode(nodeId.Value); var modifiedParent = parent.AddChild(v); //only save node back if it actually added the child value if (!ReferenceEquals(parent, modifiedParent)) { _memory.SetNode(modifiedParent); } } childId = node.Id; } nodeId = childId; } ITrieNode <TK, TV> modifiedNode = node; // if we are tracking a node it is an added leaf and must be saved if (node != null) { modifiedNode = modify(node); } // otherwise get the identified node by id if there is one else if (nodeId.HasValue) { node = _memory.GetNode(nodeId.Value); modifiedNode = modify(node); } if (!ReferenceEquals(node, modifiedNode)) { _memory.SetNode(modifiedNode); } }
public MatchUoW(int index, char currentChar, ITrieNode currentNode) { Condition.Requires(currentNode).IsNotNull(); this.StartingIndex = index; this.CurrentIndex = index; this.CurrentWord = new string(currentChar, 1); this.CurrentNode = currentNode; }
internal TrieNode <TK, TV> Cast(ITrieNode <TK, TV> node) { if (node is TrieNode <TK, TV> realized) { return(realized); } return(new TrieNode <TK, TV>(node.Id, node.Value, node.Children.ToList())); }
/// <summary> /// Create an empty trie with an empty root node. /// </summary> public AbstractTrie(Func <TKey, IEnumerable <TKeyBit> > keyMapper) { if (keyMapper == null) { throw new ArgumentNullException("keyMapper", "Key Mapper function cannot be null"); } this._keyMapper = keyMapper; this._root = this.CreateRoot(default(TKeyBit)); this.KeyBitComparer = Comparer <TKeyBit> .Default; }
/// <summary> /// Gets whether the Trie contains a specific key /// </summary> /// <param name="key">Key</param> /// <param name="requireValue">Whether the key is required to have a value associated with it in order to be considered as being contained</param> /// <returns>True if the Trie contains the given key and meets the value requirement</returns> public bool ContainsKey(TKey key, bool requireValue) { ITrieNode <TKeyBit, TValue> node = this.Find(key); if (node == null) { return(false); } return(!requireValue || node.HasValue); }
public void Load(Stream stream) { var node = _settings.Serializer.Load(stream, _settings); var persister = new Persister <TK, TV, TI> { Settings = _settings }; var root = persister.ToTrieNode(node); _root = root; }
/// <summary> /// Children for this node indexed by their char /// </summary> /// <param name="c">Child word.</param> /// <returns>Child node.</returns> public ITrieNode this[char c] { get { ITrieNode item = null; _children.TryGetValue(c, out item); return(item); } set { _children[c] = value; } }
private static int GetNodeDepth <TKeyBit, TValue>(ITrieNode <TKeyBit, TValue> n) where TValue : class { var depth = 0; while (!n.IsRoot) { depth++; n = n.Parent; } return(depth); }
/// <summary> /// Moves to the Node associated with the given Key creating new nodes if necessary /// </summary> /// <param name="key">Key</param> /// <returns>Trie Node</returns> public ITrieNode <TKeyBit, TValue> MoveToNode(TKey key) { ITrieNode <TKeyBit, TValue> node = _root; IEnumerable <TKeyBit> bs = this._keyMapper(key); foreach (TKeyBit b in bs) { node = node.MoveToChild(b); } return(node); }
/// <summary> /// Adds a new key value pair, overwriting the existing value if the given key is already in use /// </summary> /// <param name="key">Key to search for value by</param> /// <param name="value">Value associated with key</param> public void Add(TKey key, TValue value) { ITrieNode <TKeyBit, TValue> node = _root; IEnumerable <TKeyBit> bs = this._keyMapper(key); foreach (TKeyBit b in bs) { node = node.MoveToChild(b); } node.Value = value; }
/// <summary> /// Checks to make sure that a given item is stored at the point specified by the list of elements. /// </summary> /// <param name="storeAtPositionArray"></param> /// <param name="Item"></param> /// <returns></returns> public bool Contains(IList <ArrayPathType> storeAtPositionArray, StoredItemType Item) { List <ITrieNode <ArrayPathType, StoredItemType> > myRootItem = Root; ITrieNode <ArrayPathType, StoredItemType> lastMatch = null; for (int i = 0; i < storeAtPositionArray.Count; i++) { var Match = SearchSubtreeForMatchingType(storeAtPositionArray[i], myRootItem); if (Match == null) { return(default);
/// <summary> /// Tries to get a child of this node which is associated with a key bit /// </summary> /// <param name="key">Key</param> /// <param name="child">Child</param> /// <returns></returns> public bool TryGetChild(TKeyBit key, out ITrieNode <TKeyBit, TValue> child) { try { this.EnterReadLock(); return(this._children.TryGetValue(key, out child)); } finally { this.ExitReadLock(); } }
public void TrieContractFind2() { ITrie <String, char, String> trie = this.GetInstance(); ITrieNode <char, String> node = trie.Find("test"); Assert.IsNull(node); trie.Add("test", "a"); node = trie.Find("test"); Assert.IsNotNull(node); Assert.AreEqual("a", node.Value); }
/// <summary> /// Filters based upon an internal Trie /// </summary> /// <param name="ch"></param> /// <returns></returns> private int Filter(char ch) { int lookAhead = 0; ITrieNode <char, string> node = this.trie[ch]; while (node != null) { if (node.HasValue) { // found StartToken string endToken = node.Value; int length = endToken.Length; // move to end of StartToken this.position += lookAhead; for (int i = 0; i < length; i++) { int ch2 = this.Read(false); if (ch < 0) { throw new UnexpectedEndOfFile("Expected " + endToken, this.FilePath, this.Line, this.Column); } if (ch2 != endToken[i]) { // reset search while (i > 0) { i--; this.PutBack(); } i--; } } return(this.Read(true)); } else { lookAhead++; int pk = this.Peek(lookAhead); if (pk < 0) { return(ch); } node = node[(char)pk]; } } return(ch); }
/// <summary> /// Finds and returns a Node for the given sequence of Key Bits /// </summary> /// <param name="bs">Key Bits</param> /// <returns>Null if the Key does not map to a Node</returns> /// <remarks> /// The ability to provide a specific sequence of key bits may be useful for custom lookups where you don't necessarily have a value of the <strong>TKey</strong> type but do have values of the <strong>TKeyBit</strong> type /// </remarks> public ITrieNode <TKeyBit, TValue> Find(IEnumerable <TKeyBit> bs) { ITrieNode <TKeyBit, TValue> node = this._root; foreach (TKeyBit b in bs) { //Bail out early if key does not exist if (!node.TryGetChild(b, out node)) { return(null); } } return(node); }
public void TrieContractFind4() { ITrie <String, char, String> trie = this.GetInstance(); ITrieNode <char, String> node = trie.Find("test"); Assert.IsNull(node); trie.Add("test", "a"); //Find with a custom key mapper node = trie.Find("testing", (s => s.Substring(0, 4).ToCharArray())); Assert.IsNotNull(node); Assert.AreEqual("a", node.Value); }
/// <summary> /// tests if the current node can handle the next char, and updates match if so /// </summary> /// <param name="nextChar"></param> /// <returns></returns> public bool MoveNext(char nextChar) { var node = this.CurrentNode[nextChar]; if (node == null) { return(false); } //increment index this.CurrentIndex++; this.CurrentNode = node; this.CurrentWord = this.CurrentWord + nextChar; return(true); }
/// <summary> /// Creates a URI interning it if interning is enabled via the <see cref="Options.InternUris">Options.InternUris</see> /// </summary> /// <param name="uri">String URI</param> /// <returns></returns> /// <remarks> /// When URI interning is disabled this is equivalent to just invoking the constructor of the <see cref="Uri">Uri</see> class /// </remarks> public static Uri Create(String uri) { if (Options.InternUris) { ITrieNode <char, Uri> node = _uris.MoveToNode(uri); if (node.HasValue) { return(node.Value); } Uri u = new Uri(uri); node.Value = u; return(node.Value); } return(new Uri(uri)); }
public PersistNode <TK, TV, TI> ToPersistable(ITrieNode <TK, TV, TI> node) { var persistable = new PersistNode <TK, TV, TI> { Children = node.Children().Select(p => { var c = ToPersistable(p.Value); c.Key = p.Key; return(c); }).ToList(), Values = node.Pairs().ToList() }; return(persistable); }
static void TraverseChildren(ITrieNode <char, string> node, Action <ITrieNode <char, string> > nodeFunc, Action <ITrieNode <char, string> > leafFunc) { if (node != null && node.HasValue) { nodeFunc(node); } if (node == null || node.IsLeaf) { leafFunc(node); return; } node.Children.ToList().ForEach(n => { TraverseChildren(n, nodeFunc, leafFunc); }); }
/// <summary> /// tests if the current node can handle the next char, and updates match if so /// </summary> /// <param name="nextChar"></param> /// <returns></returns> public bool MoveNext(char nextChar) { var node = this.CurrentNode[nextChar]; if (node == null) return false; //increment index this.CurrentIndex++; this.CurrentNode = node; this.CurrentWord = this.CurrentWord + nextChar; return true; }