Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

120
LINES

< > BotCompany Repo | #1030153 // StringTrie

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (3229L/19K).

// A = type of value in nodes.
// Can be case-sensitive or case-insensitive
// values can't be null
sclass StringTrie<A> {
  A value;
  TreeMap<S, StringTrie<A>> children;
  
  *() {}
  *(A *value) {}
  *(Iterable<S> strings) { addAll(strings, null); } // give all leaves null values
  
  void makeCaseInsensitive() {
    children = asCIMap(children);
  }
  
  bool isCaseInsensitive() {
    ret isCIMap(children);
  }
  
  void addAll(Iterable<S> strings, A value) {
    fOr (S s : strings)
      add(s, value);
  }
  
  void put(S string, A value) { add(string, value); }
  
  void add(S string, A value) {
    ifdef StringTrie_debug printFunctionCall("StringTrie add", string, value); endifdef
    // case 1: empty string
    if (empty(string)) ret with this.value = value;
    
    // case 2: some prefix of new string exists
    S existingPrefix = longestLocalPrefix(string);
      
    ifdef StringTrie_debug print(+existingPrefix); endifdef
    if (nempty(existingPrefix)) {
      StringTrie<A> child = children.get(existingPrefix);
      S substring = substring(string, l(existingPrefix));
      
      // case 2a: new string is complete suffix of existing child
      ifdef StringTrie_debug print(+child); endifdef
      if (child != null)
        ret with child.add(substring, value);
      
      // case 2b: make new branch
      StringTrie<A> branch = newChild(null);
      if (branch.children == null) branch.children = new TreeMap;
      Map.Entry<S, StringTrie<A>> e = children.higherEntry(existingPrefix);
      S key = e.getKey();
      child = e.getValue();
      children.remove(e.getKey());
      children.put(existingPrefix, branch);
      branch.children.put(substring(key, l(existingPrefix)), child);
      branch.children.put(substring, newChild(value));
      ret;
    }
   
    // case 3: no existing prefix, just add new child
    if (children == null) children = new TreeMap;
    children.put(string, newChild(value));
  }
  
  // returns TreeMap or ciMap
  Map<S, A> asMap() {
    Map<S, A> map = isCaseInsensitive() ? ciMap() : new TreeMap;
    new StringBuilder buf;
    collectMap(buf, map);
    ret map;
  }
  
  private void collectMap(StringBuilder buf, Map<S, A> map) {
    if (value != null) map.put(str(buf), value);
    int n = l(buf);
    for (S string, StringTrie<A> child : children) {
      buf.append(string);
      child.collectMap(buf, map);
      buf.setLength(n);
    }
  }
  
  toString {
    new StringBuilder buf;
    if (value != null) {
      buf.append("\"\" => ").append(value).append("\n");
      childrenToString(buf, 2);
    } else
      childrenToString(buf, 0);
    ret str(buf);
  }
  
  void toString(StringBuilder buf, int indent) {
    if (value != null)
      buf.append(" => ").append(value);
    buf.append("\n");
    childrenToString(buf, indent+2);
  }
  
  void childrenToString(StringBuilder buf, int indent) {
    for (S string, StringTrie<A> child : children) {
      buf.append(spaces(indent)).append(quote(string));
      child.toString(buf, indent);
    }
  }
  
  private StringTrie<A> newChild(A value) {
    StringTrie<A> child = new(value);
    if (isCaseInsensitive()) child.makeCaseInsensitive();
    ret child;
  }
  
  S longestLocalPrefix(S string) {
    ret isCaseInsensitive()
      ? longestCommonPrefixOfCISetAndString(string, navigableKeys(children))
      : longestCommonPrefixOfNavigableSetAndString(string, navigableKeys(children));
  }
  
  Set<S> childStrings() { ret keys(children); }
  StringTrie<A> getChild(S string) { ret children.get(string); }
  NavigableMap<S, StringTrie<A>> children() { ret children; }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1030153
Snippet name: StringTrie
Eternal ID of this version: #1030153/29
Text MD5: 864525b0eaada21cee2cdf106462822a
Transpilation MD5: 785ea2d584e69ea9f47e69fc6380c13e
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-01-13 21:00:58
Source code size: 3729 bytes / 120 lines
Pitched / IR pitched: No / No
Views / Downloads: 288 / 635
Version history: 28 change(s)
Referenced in: #1030167 - ListTrie - generalized StringTrie over lists instead of strings
#1030176 - StringTrie, lean mode
#1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)