/// <summary> /// Performs string auto completing. Instead of strings it returns node at the en of matching sequence. /// </summary> /// <param name="matching">The matching.</param> /// <param name="rules">The rules.</param> /// <returns></returns> public List <KeyValuePair <float, StringTreeNode> > AutoComplete([NotEmpty] string matching, [NotNull] StringMatchingRules rules) { List <KeyValuePair <float, StringTreeNode> > result = new List <KeyValuePair <float, StringTreeNode> >(); for (int i = 0; i < root.children.Count; i++) { root.children[i].AutoComplete(matching, 0, rules.InitialScore, rules, result); } return(result); }
/// <summary> /// Matches the specified STR. /// </summary> /// <param name="str">The STR.</param> /// <param name="position">The position.</param> /// <param name="score">The score.</param> /// <param name="rules">The rules.</param> /// <param name="result">The result.</param> internal protected void Match(string str, int position, float score, StringMatchingRules rules, List <KeyValuePair <float, string> > result) { // If cannot procceed, return. if (score < rules.MinScoreFilter) { return; } // This is special case if appending. if (str.Length == position) { // We decrement the score. score -= rules.CharMissingPenaltyAtEnd; if (score < rules.MinScoreFilter) { return; } // We do the search. if (internalString != string.Empty) { result.Add(new KeyValuePair <float, string>(score, internalString)); } // We now expand to all children. for (int i = 0; i < children.Count; i++) { children[i].Match(str, position, score, rules, result); } return; } // We first check if matched. if (str[position] == character) { // We check if we can match against internal string. if (internalString != string.Empty) { float xscore = score - rules.CharIgnorePenalty * (str.Length - position - 1); if (xscore >= rules.MinScoreFilter) { result.Add(new KeyValuePair <float, string>(score, internalString)); } } // We proceed matching for (int i = 0; i < children.Count; i++) { children[i].Match(str, position + 1, score, rules, result); } } else if (char.ToLowerInvariant(str[position]) == char.ToLowerInvariant(character)) { float xscore = score + rules.CharCaseMismatchPenalty; // We check if we have internal string. if (internalString != string.Empty) { float xxscore = score - rules.CharIgnorePenalty * (str.Length - position - 1); if (xxscore >= rules.MinScoreFilter) { result.Add(new KeyValuePair <float, string>(score, internalString)); } } // We proceed matching. for (int i = 0; i < children.Count; i++) { children[i].Match(str, position + 1, xscore, rules, result); } } else { // Ignore character case. for (int i = 0; i < children.Count; i++) { children[i].Match(str, position, score - rules.CharIgnorePenalty, rules, result); } // Insert character case. for (int j = 0; j < children.Count; j++) { children[j].Match(str, position + 1, score - rules.CharMissingPenalty, rules, result); } } }
/// <summary> /// We do a search using supplied rules. /// </summary> /// <param name="matching"></param> /// <param name="rules"></param> public List <KeyValuePair <float, string> > Search([NotEmpty] string matching, [NotNull] StringMatchingRules rules) { // We start the progress. List <KeyValuePair <float, string> > result = new List <KeyValuePair <float, string> >(); for (int i = 0; i < root.children.Count; i++) { root.children[i].Match(matching, 0, rules.InitialScore, rules, result); } // We return the result. return(result); }
/// <summary> /// Auto completes the string. /// </summary> /// <param name="str">The STR.</param> /// <param name="position">The position.</param> /// <param name="score">The score.</param> /// <param name="rules">The rules.</param> /// <param name="result">The result.</param> internal protected void AutoComplete(string str, int position, float score, StringMatchingRules rules, List <KeyValuePair <float, StringTreeNode> > result) { // If cannot procceed, return. if (score < rules.MinScoreFilter) { return; } // Check if last character. if (position + 1 == str.Length) { result.Add(new KeyValuePair <float, StringTreeNode>(score, this)); return; } // We first check if matched. if (str[position] == character) { // We check if we can match against internal string. if (internalString != string.Empty) { float xscore = score - rules.CharIgnorePenalty * (str.Length - position - 1); if (xscore >= rules.MinScoreFilter) { result.Add(new KeyValuePair <float, StringTreeNode>(score, this)); } } // We proceed matching for (int i = 0; i < children.Count; i++) { children[i].AutoComplete(str, position + 1, score, rules, result); } } else if (char.ToLowerInvariant(str[position]) == char.ToLowerInvariant(character)) { float xscore = score + rules.CharCaseMismatchPenalty; // We check if we have internal string. if (internalString != string.Empty) { float xxscore = score - rules.CharIgnorePenalty * (str.Length - position - 1); if (xxscore >= rules.MinScoreFilter) { result.Add(new KeyValuePair <float, StringTreeNode>(score, this)); } } // We proceed matching. for (int i = 0; i < children.Count; i++) { children[i].AutoComplete(str, position + 1, xscore, rules, result); } } else { // Ignore character case. for (int i = 0; i < children.Count; i++) { children[i].AutoComplete(str, position, score - rules.CharIgnorePenalty, rules, result); } // Insert character case. for (int j = 0; j < children.Count; j++) { children[j].AutoComplete(str, position + 1, score - rules.CharMissingPenalty, rules, result); } } }