Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>int IndexOfAny(String[] rgs)</strong> would indeed be nice but it's nominally an O(n^2) operation. If, in your application, the set of strings <em>rgs</em> is large and always the same, the most efficient approach is to load them into a <a href="http://en.wikipedia.org/wiki/Trie" rel="nofollow noreferrer">trie</a> data structure once, and then use the trie repeatedly to search for them within the unknown strings given at runtime.</p> <p>Here is the relevant code, adapted from a C# trie source I found on the web, attributed to "Kerry D. Wong." In my version, each string in the trie has a "payload" of generic type <em>TValue</em>. To use this trie to simply search for substrings, the payload could always be set to <em>true</em>, as illustrated with <em>simple_trie</em>.</p> <p>The other thing I changed here is that this trie automatically adapts allow for storage of arbitrary Unicode strings. The array at each node—which characterizes a trie—adjusts its base and length to accomodate the range of Unicode characters which need to be stored at that node. This allows for case-sensitive matching, for example.</p> <p>The C# 3.0 initialization syntax is handy for this trie, but enabling it requires a dummy implementation of <em>IEnumerable</em> in order to compile. The CLR doesn't seem to call GetEnumerator() and I suggest that you don't try to enumerate with its result either.</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; // only used in Main() class Program { // trie with payload of type &lt;String&gt; static Trie&lt;String&gt; value_trie = new Trie&lt;String&gt; { { "rabbit", "cute" }, { "giraffe", "tall" }, { "ape", "smart" }, { "hippo", "large" }, }; // degenerate case of a trie without payload static Trie&lt;bool&gt; simple_trie = new Trie&lt;bool&gt; { { "rabbit", true }, { "giraffe", true }, { "ape", true }, { "hippo", true }, }; static void Main(String[] args) { String s = "Once upon a time, a rabbit met an ape in the woods."; // Retrieve payloads for words in the string. // // output: // cute // smart foreach (String word in value_trie.AllSubstringValues(s)) Console.WriteLine(word); // Simply test a string for any of the words in the trie. // Note that the Any() operator ensures that the input is no longer // traversed once a single result is found. // // output: // True Console.WriteLine(simple_trie.AllSubstringValues(s).Any(e=&gt;e)); s = "Four score and seven years ago."; // output: // False Console.WriteLine(simple_trie.AllSubstringValues(s).Any(e =&gt; e)); } } class TrieNode&lt;TValue&gt; { private TrieNode&lt;TValue&gt;[] nodes = null; private TValue m_value = default(TValue); private Char m_base; public Char Base { get { return m_base; } } public bool IsEnd { get { return !m_value.Equals(default(TValue)); } } public TValue Value { get { return m_value; } set { m_value = value; } } public IEnumerable&lt;TrieNode&lt;TValue&gt;&gt; Nodes { get { return nodes; } } public TrieNode&lt;TValue&gt; this[char c] { get { if (nodes != null &amp;&amp; m_base &lt;= c &amp;&amp; c &lt; m_base + nodes.Length) return nodes[c - m_base]; return null; } } public TrieNode&lt;TValue&gt; AddChild(char c) { if (nodes == null) { m_base = c; nodes = new TrieNode&lt;TValue&gt;[1]; } else if (c &gt;= m_base + nodes.Length) { Array.Resize(ref nodes, c - m_base + 1); } else if (c &lt; m_base) { Char c_new = (Char)(m_base - c); TrieNode&lt;TValue&gt;[] tmp = new TrieNode&lt;TValue&gt;[nodes.Length + c_new]; nodes.CopyTo(tmp, c_new); m_base = c; nodes = tmp; } TrieNode&lt;TValue&gt; node = nodes[c - m_base]; if (node == null) { node = new TrieNode&lt;TValue&gt;(); nodes[c - m_base] = node; } return node; } }; class Trie&lt;TValue&gt; : System.Collections.IEnumerable { private TrieNode&lt;TValue&gt; _root = new TrieNode&lt;TValue&gt;(); // This dummy enables C# 3.0 initialization syntax public System.Collections.IEnumerator GetEnumerator() { return null; } public void Add(String s, TValue v) { TrieNode&lt;TValue&gt; node = _root; foreach (Char c in s) node = node.AddChild(c); node.Value = v; } public bool Contains(String s) { TrieNode&lt;TValue&gt; node = _root; foreach (Char c in s) { node = node[c]; if (node == null) return false; } return node.IsEnd; } public TValue Find(String s_in) { TrieNode&lt;TValue&gt; node = _root; foreach (Char c in s_in) { node = node[c]; if (node == null) return default(TValue); } return node.Value; } public IEnumerable&lt;TValue&gt; FindAll(String s_in) { TrieNode&lt;TValue&gt; node = _root; foreach (Char c in s_in) { node = node[c]; if (node == null) break; if (node.Value != null) yield return node.Value; } } public IEnumerable&lt;TValue&gt; AllSubstringValues(String s) { int i_cur = 0; while (i_cur &lt; s.Length) { TrieNode&lt;TValue&gt; node = _root; int i = i_cur; while (i &lt; s.Length) { node = node[s[i]]; if (node == null) break; if (node.Value != null) yield return node.Value; i++; } i_cur++; } } }; </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload