This is a lovely bit of recursion which will find the first occurrence of any number of sub-strings in a string, and allows you to add a number of "protection" delimiters so that strings inside will not be found - if you see what I mean...
delimiters = new FindDelimiters { { "'", "'" } };
Assert.AreEqual(28,
"do not find 'x' but do find x".Find(delimiters, "x"));
This is useful for parsing things like html/xml attributes
/// <summary>
/// <para>Find the first index of any of the passed string values</para>
/// </summary>
/// <param name="text">Text to search</param>
/// <param name="startIndex">Staring index</param>
/// <param name="delimiters">Protected delimiters</param>
/// <param name="stringComparison">String Comparison</param>
/// <param name="values">Values to find, finds first</param>
/// <returns>FindResult, which is an implicit int, -1 = not found</returns>
public static FindResult Find(
this string text, int startIndex, FindDelimiters delimiters,
StringComparison stringComparison, params string[] values) {
if (text == null || values == null
|| startIndex < 0 || startIndex > text.Length) return null;
var found = (from v in values
let i = text.IndexOf(v, startIndex, stringComparison)
orderby i
where i != -1
select new FindResult {Found = v, Index = i})
.FirstOrDefault();
if (found != null
&& delimiters != null
&& delimiters.Count > 0) {
// check for delimiter open before the found value
var open = (from d in delimiters
let iOpen = text
.IndexOf(d.Key, startIndex, stringComparison)
orderby iOpen
where iOpen != -1 && iOpen < found.Index
select new {Delimiter = d, Index = iOpen})
.FirstOrDefault();
if (open != null) {
// check for valid close on found delimiter
var close = Find(text,
open.Index + 1, stringComparison, open.Delimiter.Value);
if (close != null)
// find after delimiter closed
return Find(text,
close.Index + 1, delimiters, stringComparison, values);
}
}
return found;
}
/// <summary>
/// <para>Result of a call to find</para>
/// <para>Implicit conversion to int,
/// if null (not found) will return -1</para>
/// </summary>
public class FindResult {
public string Found { get; internal set; }
public int Index { get; internal set; }
public static implicit operator int(FindResult r) {
return r == null ? -1 : r.Index;
}
}
/// <summary>
/// <para>Strings that can wrap another string,
/// for example a quote</para>
/// </summary>
public class FindDelimiters:Dictionary<string,string> {}
| < | May 2012 | |||||
|---|---|---|---|---|---|---|
| S | M | T | W | T | F | S |
| 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
Add-ins AJAX ASP.NET MVC Browsers C# Caching CodeDom Compression CORS CSS CV Data Database DependencyResolver Development Dynamic Entity Framework Error Handling Extend File Upload Forms GDI+ HTML HTML Editor HTTP Interfaces JavaScript JQuery MCE MetadataProvider MSBuild Numbers Objects Patterns Progressive Enhancement Projects Publish Regex Resources Security SEO SMTP Source Control Strings Sub-Collections TDD Templates Tools Twitter User Interface WCF Web Development WHS WMC XLinq XML
15/05/2012
WindowsAzure
Announcing the MEET Windows Azure Event! Streamed online June 7th. Register at http://t.co/bObzTAuL #MEETAzure #WindowsAzure
10/05/2012
kevinwhinnery
Comparing Titanium and PhoneGap - A common question I get asked at developer events and conferences is how... http://t.co/Zq2eND6B
09/05/2012
brianleroux
PhoneGap goals and philosophy: http://t.co/wkq8wI2T
just now
ChaseDiane
encrypting phonegap android by joseesfera: currently being developed for PhoneGap app, we need to encrypt the co... http://t.co/qCSGs9iX
just now
rgonv
#Tech Post: Bing Search API now available on Windows Azure Marketplace: The Bing Search API is now available on ... http://t.co/iBvXOjbC