How can I most efficiently check to see if an input string starts with a string that belongs in a list of strings?
For example possiblePrefixes = "1234", "1235", "1236". If input = "1235av2425" should return true. If input = "1237352ko" should return false.
you can use Any for this. the concept here is you need to check whether there is any item in the list which is the prefix for the given string.
List<string> list = new List<string>() { "1234", "1235", "1236" };
string input = "1237352ko";
var exisits = list.Any(x => input.StartsWith(x)); //returns false
when string input = "1235av2425"; it will return true
An efficient datastructure for this type of search would be a prefix tree (aka "Trie").
For your example data such a tree might look something like this:
123
|-4
|-5
|-6
This could allow a lookup time that is independent of the number of prefixes you want to check against.
But as far as I know there are no builtin types for this, so you would either need to find a library, or implement it yourself.
The solution using Any and StartsWith will be the best in most cases. Looking for an optimized solution will only be necessary if you have a long list of possible prefixes and/or a long list of texts to check against the same prefixes.
In that case, using a pre-compiled regular expression built once from the list of possible prefixes and then re-used for multiple checks might be a little faster.
// Build regular expression once
string[] possiblePrefixes = new string[] { "1234", "1235", "1236" };
var escaped = possiblePrefixes.Select(p => Regex.Escape(p));
string pattern = "^(" + string.Join("|", escaped) + ").*";
Regex regEx = new Regex(pattern, RegexOptions.Compiled);
// Now use it multiple times
string input = "1235av2425";
bool result = regEx.IsMatch(input);
Following are the 2 solutions
Solution # 1 (using Lambda Expression)
List<string> possiblePrefixes = new List<string>() { "1234", "1235", "1236" };
string input = "1235av2425";
var result = possiblePrefixes.Any(x => input.StartsWith(x));
Console.WriteLine(result); //returns True
Solution # 2 (using SQL)
List<string> possiblePrefixes = new List<string>() { "1234", "1235", "1236" };
string input = "1235av2425";
var result = (from val in possiblePrefixes
where input.StartsWith(val)
select val).Any();
Console.WriteLine(result); //returns True
from the following code I am trying to get the data from the script variable. I'm interested in the text between ""
var code = "a37965dcd8421328a767c697448ed735";
XPathResult xpathResult = geckoWebBrowser1.Document.EvaluateXPath("/html/body/table[3]/tbody/tr[1]/td[2]/script");
var foundNodes = xpathResult.GetNodes();
foreach (var node in foundNodes)
{
var x = node.TextContent; // get text text contained by this node (including children)
GeckoHtmlElement element = node as GeckoHtmlElement; //cast to access.. inner/outerHtml
string inner = element.InnerHtml;
string outer = element.OuterHtml;
String pattent = ".[0-9a-zA-Z]{34}$.";
Match match = Regex.Match(inner, pattent);
regex is correct? what am I doing wrong?
Your Regex string can try to use [0-9a-zA-Z]{32,34} instead of .[0-9a-zA-Z]{34}$.
The . could be removed.
regex online
Your Regex rule can try like this:
bool result = Regex.Match(inner, #"^[0-9a-zA-Z]{32,34}$").Success;
Console.WriteLine(result);
If result equal true, it match success!
I want to get lastindexof character from url which comes from the database on the basis of '\' or '//'
Say for example i have string like this
Administration\Masters\EmployeePulseDetailsMaster.aspx
Administration/Masters/SearchKnowYourCollegues.aspx
Administration//SMS//PushSMS.aspx
I am using that code
foreach (var item in SessionClass.UserDetails.SubModules)
{
if (Request.RawUrl.Contains(item.PageURL.Substring(item.PageURL.LastIndexOf('\\') + 1))
|| Request.RawUrl.Contains(item.PageURL.Substring(item.PageURL.LastIndexOf('/') + 1)))
{
Response.RedirectPermanent("~/Login.aspx");
}
}
You can use a regular expression to find the last occurrence of any character in a group by constructing a regular expression that looks like this:
[target-group][^target-group]*$
In your case, the target group is [/\\], so the search would look like this:
var match = Regex.Match(s, #"[/\\][^/\\]*$");
Here is a running example:
var data = new[] {
#"quick/brown/fox"
, #"jumps\over\the\lazy\dog"
, #"Administration\Masters\EmployeePulseDetailsMaster.aspx"
, #"Administration/Masters/SearchKnowYourCollegues.aspx"
, #"Administration//SMS//PushSMS.aspx"
};
foreach (var s in data) {
var m = Regex.Match(s, #"[/\\][^/\\]*$");
if (m.Success) {
Console.WriteLine(s.Substring(m.Index+1));
}
}
This prints
fox
dog
EmployeePulseDetailsMaster.aspx
SearchKnowYourCollegues.aspx
PushSMS.aspx
Demo.
I guess you want to determine if the name of the current page is in the list of SessionClass.UserDetails.SubModules. Then i'd use Request.Url.Segments.Last() to get only the name of the current page(f.e. PushSMS.aspx) and System.IO.Path.GetFileName to get the name of each url. GetFileName works with / or \:
string pageName = Request.Url.Segments.Last();
bool anyMatch = SessionClass.UserDetails.SubModules
.Any(module => pageName == System.IO.Path.GetFileName(module.PageURL));
if(anyMatch) Response.RedirectPermanent("~/Login.aspx");
You need to add using System.Linq; for Enumerable.Any.
I am trying to get the href link out of the following HTML code using mshtml in C# (WPF).
<a class="button_link" href="https://rhystowey.com/account/confirm_email/2842S-B2EB5-136382?t=1&sig=b0dbd522380a21007d8c375iuc583f46a90365d9&iid=am-130280753913638201274485430&ac=1&uid=1284488216&nid=18+308" style="border:none;color:#0084b4;text-decoration:none;color:#ffffff;font-size:13px;font-weight:bold;font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;">Confirm your account now</a>
I have tried using the following code to make this work by using mshtml in C# (WPF) but I have failed miserably.
HTMLDocument mdoc = (HTMLDocument)browser.Document;
string innerHtml = mdoc.body.outerText;
string str = "https://rhystowey.com/account/confirm_email/";
int index = innerHtml.IndexOf(str);
innerHtml = innerHtml.Remove(0, index + str.Length);
int startIndex = innerHtml.IndexOf("\"");
string str3 = innerHtml.Remove(startIndex, innerHtml.Length - startIndex);
string thelink = "https://rhystowey.com/account/confirm_email/" + str3;
Can someone please help me to get this to work.
Use this:
var ex = new Regex("href=\"(.*)\" style");
var tag = "<a class=\"button_link\" href=\"https://rhystowey.com/account/confirm_email/2842S-B2EB5-136382?t=1&sig=b0dbd522380a21007d8c375iuc583f46a90365d9&iid=am-130280753913638201274485430&ac=1&uid=1284488216&nid=18+308\" style=\"border:none;color:#0084b4;text-decoration:none;color:#ffffff;font-size:13px;font-weight:bold;font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;\">Confirm your account now</a>";
var address = ex.Match(tag).Groups[1].ToString();
But you should extend it with checks because for instance Groups[1] could be out of range.
In your example
HTMLDocument mdoc = (HTMLDocument)browser.Document;
string innerHtml = mdoc.body.outerText;
var ex = new Regex("href=\"([^\"\"]+)\"");
var address = ex.Match(innerHtml).Groups[1].ToString();
will match the first href="...". Or you select all occurrences:
var matches = (from Match match in ex.Matches(innerHtml) select match.Groups[1].Value).ToList();
This will give you a List<string> with all the links in your HTML. To filter this, you can either go this way
var wantedMatches = matches.Where(m => m.StartsWith("https://rhystowey.com/account/confirm_email/"));
which is more flexible because you could check against a list of start strings or whatever. Or you do it in your regex, which will lead in better performance:
var ex = new Regex("href=\"(https://rhystowey\\.com/account/confirm_email/[^\"\"]+)\"");
Bringing it all together to what you want as far as I understand
var ex = new Regex("href=\"(https://rhystowey\\.com/account/confirm_email/[^\"\"]+)\"");
var matches = (from Match match in ex.Matches(innerHTML)
where match.Groups.Count >= 1
select match.Groups[1].Value).ToList();
var firstAddress = matches.FirstOrDefault();
firstAddress holds your link, if there is one.
If your link will always start with the same path and isn't repeated on the page, you can use this (untested):
var match = Regex.Match(html, #"href=""(?<href>https\:\/\/rhystowey\.com\/account\/confirm_email\/[^""]+)""");
if (match.Success)
{
var href = match.Groups["href"].Value;
....
}
I would like to use regular expressions to replace multiple groups with corresponding replacement string.
Replacement table:
"&" -> "__amp"
"#" -> "__hsh"
"1" -> "5"
"5" -> "6"
For example, for the following input string
"a1asda&fj#ahdk5adfls"
the corresponding output string is
"a5asda__ampfj__hshahdk6adfls"
Is there any way to do that?
Given a dictionary that defines your replacements:
IDictionary<string, string> map = new Dictionary<string, string>()
{
{"&","__amp"},
{"#","__hsh"},
{"1","5"},
{"5","6"},
};
You can use this both for constructing a Regular Expression, and to form a replacement for each match:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Live example: http://rextester.com/rundotnet?code=ADDN57626
This uses a Regex.Replace overload which allows you to specify a lambda expression for the replacement.
It has been pointed out in the comments that a find pattern which has regex syntax in it will not work as expected. This could be overcome by using Regex.Escape and a minor change to the code above:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys.Select(k => Regex.Escape(k))));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Given a dictionary like in the other answers, you can use an "aggregate" to map each pattern in the dictionary to a replacement. This will give you far more flexibility that the other answers, as you can have different regex options for each pattern.
For example, the following code will "romanize" greek text (https://en.wikipedia.org/w/index.php?title=Romanization_of_Greek§ion=3#Modern_Greek, Standard/UN):
var map = new Dictionary<string,string>() {
{"α[ύυ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "av"}, {"α[ύυ]", "af"}, {"α[ϊΐ]", "aï"}, {"α[ιί]", "ai"}, {"[άα]", "a"},
{"β", "v"}, {"γ(?=[γξχ])", "n"}, {"γ", "g"}, {"δ", "d"},
{"ε[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "ev"}, {"ε[υύ]", "ef"}, {"ει", "ei"}, {"[εέ]", "e"}, {"ζ", "z"},
{"η[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "iv"}, {"η[υύ]", "if"}, {"[ηήιί]", "i"}, {"[ϊΐ]", "ï"},
{"θ", "th"}, {"κ", "k"}, {"λ", "l"}, {"\\bμπ|μπ\\b", "b"}, {"μπ", "mb"}, {"μ", "m"}, {"ν", "n"},
{"ο[ιί]", "oi"}, {"ο[υύ]", "ou"}, {"[οόωώ]", "o"}, {"ξ", "x"}, {"π", "p"}, {"ρ", "r"},
{"[σς]", "s"}, {"τ", "t"}, {"[υύϋΰ]", "y"}, {"φ", "f"}, {"χ", "ch"}, {"ψ", "ps"}
};
var input = "Ο Καλύμνιος σφουγγαράς ψυθίρισε πως θα βουτήξει χωρίς να διστάζει.";
map.Aggregate(input, (i, m) => Regex.Replace(i, m.Key, m.Value, RegexOptions.IgnoreCase));
returning (without modifying the "input" variable:
"o kalymnios sfoungaras psythirise pos tha voutixei choris na distazei."
You can of course use something like:
foreach (var m in map) input = Regex.Replace(input, m.Key, m.Value, RegexOptions.IgnoreCase);
which does modify the "input" variable.
Also you can add this to improve performance:
var remap = new Dictionary<Regex, string>();
foreach (var m in map) remap.Add(new Regex(m.Key, RegexOptions.IgnoreCase | RegexOptions.Compiled), m.Value);
cache or make static the remap dictionary and then use:
remap.Aggregate(input, (i, m) => m.Key.Replace(i, m.Value));
How about using string.Replace()?
string foo = "a1asda&fj#ahdk5adfls";
string bar = foo.Replace("&","__amp")
.Replace("#","__hsh")
.Replace("5", "6")
.Replace("1", "5");
Similar to Jamiec's answer, but this allows you to use regexes that don't match the text exactly, e.g. \. can't be used with Jamiec's answer, because you can't look up the match in the dictionary.
This solution relies on creating groups, looking up which group was matched, and then looking up the replacement value. It's a more complicated, but more flexible.
First make the map a list of KeyValuePairs
var map = new List<KeyValuePair<string, string>>();
map.Add(new KeyValuePair<string, string>("\.", "dot"));
Then create your regex like so:
string pattern = String.Join("|", map.Select(k => "(" + k.Key + ")"));
var regex = new Regex(pattern, RegexOptions.Compiled);
Then the match evaluator becomes a bit more complicated:
private static string Evaluator(List<KeyValuePair<string, string>> map, Match match)
{
for (int i = 0; i < match.Groups.Count; i++)
{
var group = match.Groups[i];
if (group.Success)
{
return map[i].Value;
}
}
//shouldn't happen
throw new ArgumentException("Match found that doesn't have any successful groups");
}
Then call the regex replace like so:
var newString = regex.Replace(text, m => Evaluator(map, m))
Just wanted to share my experience with Jamiec and Costas solutions.
If you have a problem like this:
The given key '<searched param>' was not present in the dictionary.
Bear in mind that putting regex patterns in the dictionary keys
IDictionary<string, string> map = new Dictionary<string, string>()
{
{"(?<=KeyWord){","("},
{"}",")"}
};
and using it like so
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
or so
var newStr = Regex.Replace(content, pattern, m => replacementMap[m.Value]);
may throw the aforementioned exception, because the pattern is executed before the replacement comparison, leaving only the matches to be compared to the regex keys in the dictionary. This way the key and the match may differ and throw the exception.
'(?<=KeyWord){' != '{'
So here is my solution:
I had to replace a "{" that followed a KeyWord and the corresponding "}" after that with "(" and ")" respectively.
In short making this
#"some random text KeyWord{"Value1", "Value2"} some more
random text";
into this
#"some random text KeyWord('"Value1", "Value2"') some more
random text";
Important bits
IDictionary<string, string> map = new Dictionary<string, string>()
{
{"{","('"},
{"}","')"}
};
var content = #"some random text KeyWord{"Value1", "Value2"} some more
random text";
var pattern = "((?<=KeyWord){)|((?<=\")})";
var newStr = Regex.Replace(content, pattern, m => map[m.Value]);
Hope this jumble of words will be useful to someone