I have the following code. It's working as intended, but I just wanted to know if I can change the logic behind it to make it look simpler because I believe it's redundant.
It works like this: I fetch some data and then try to pass it through a regular expression. There are three possible outcomes:
Data is fetched ok.
Data is fetched but it doesn't contain a number. So another regex is passed.
Data is not fetched. Same regex as 2) is passed. (this is what I believe could be simplified or optimised)
At first I thought that there could be a way of checking if the regular expression returns empty or not without throwing an exception, but (correct me if I'm wrong) there isn't such a thing... so that's why I included the try/catch. Without it, if the 3rd case is met, the IF returns an exception because it says that the m2[0].Groups[1].Captures[0].Value is out of bounds, of course (because it's empty).
So... is there any way to make this look more optimised?
Thank you very much!
string regexString = #" \.\.\. .*?>(.*?)<\/a>";
MatchCollection m2 = Regex.Matches(myInput, regexString, RegexOptions.Singleline);
try
{
if (m2[0].Groups[1].Captures[0].Value.All(Char.IsDigit) == false)
{
regexString = #"page=.*?"">(.*?)</a>\n.*?<a class=""pagebtn""";
m2 = Regex.Matches(myInput, regexString);
}
}
catch (ArgumentException)
{
regexString = #"page=.*?"">(.*?)</a>\n.*?<a class=""pagebtn""";
m2 = Regex.Matches(myInput, regexString);
}
I'm assuming that a more accurate description of your problem is that you wish to parse a value that may or may not be there as an integer, but that your m2[0].Groups[1].Captures[0].Value.All(Char.IsDigit) throws if Value is null.
That can then be simplified to something like this:
int parsedValue = 0;
if (m2[0].Success)
{
var value = m2[0].Groups[1].Captures[0].Value;
if (!string.IsNullOrWhiteSpace(value))
{
if (int.TryParse(value, out parsedValue))
{
// do something with parsedValue, or with the fact that the value exists and is an integer
}
}
}
You could check it with IsMatch and if it doesn't match, try your second regex, if not, nothing matches
Regex normalRegex = new Regex(#" \.\.\. .*?>(.*?)<\/a>", RegexOptions.SingleLine);
Regex secondaryRegex = new Regex(#"page=.*?"">(.*?)</a>\n.*?<a class=""pagebtn""");
int valueFound;
bool numberParsed;
if (normalRegex.IsMatch(myInput)) {
// your code to check here
// use int.TryParse to parse your value and add the result to
numberParsed = int.TryParse(m2[0].Groups[1].Captures[0].Value, out valueFound);
}
if (!numberParsed) {
if (secondaryRegex.IsMatch(myInput)) {
// second code matches
} else {
// no match
}
}
In that case you don't really need your try / catch
Related
is it possible to evaluate a single string in c#. The string itself will only be determined during run-time and therefore cannot be set before hand. please see example:
var a = "a == b";
if(a){
//do something
}
EDITED:
This is a actual example of what i would like computed:
var evaluationToBeDone = "MUST_CE_I = \"MUST_CE_I\"";
if(evaluationToBeDone){
// i will do something if the above is true
}
I see what you're trying to do, but the approach doesn't make sense. When you make a variable into an object, the program only reads it as letters, not any logic inside of the object. Try doing this:
var a = "MUST_CE_I"
var b = "\"MUST_CE_I\""
if (a == b)
{
do stuff
}
I assume you want your second string to have the " " quotes, so this should give you what you need. Even though the if statement will always return false since the two variables are not equal.
I want to get result of a value with if condition.
i have get some value in xml file.
now what I want is
if I have a variable "a" here i have assigned some values by using dataset.
and i have another variable "b" is assigned value from xml file.
for example
int a=25;
string b=">10"
now I want to check the condition if condition with out ">" because the symbol present in b variable. I dont know how to check this condition can anybody explain me how to acheive this.
I tried like this but not working
if(a+b)
You can use the DataTable.Compute-"trick" to evaulate such expressions:
int a = 25;
string b = ">10";
bool isTrue = (bool)new DataTable().Compute($"{a}{b}", null); // true
What is supported you can read at the DataColumn.Expression remarks.
if the condition is 1!=10, how to use not equal in this code .this
condition is not working what should i do.
As the documentation tells you that is not valid syntax, you have to use <> (look at operators). So a simple approach would be either to use <> in the first place or replace them:
b = b.Replace("!=", "<>");
You can have some function to remove non numeric characters:
public int Parse(string x)
{
x = Regex.Replace(x, "[^0-9.]", "");
int result = 0;
int.TryParse(x , out result);
return result;
}
If its always a number with a symbol then:
symbol = b[0];
int bval = int.Parse(b.Substring(1))
And considering your comment for comparison you can do:
if((symbol=='>'&&a>b)||
(symbol=='='&&a==b)||
(symbol=='<'&&a<b)
){
//do your magic here
}
Of course you may need only one of < = > or you may need to have separate if conditions for each, what ever suits your needs, but I just wanted to give the idea.
I tried like this
if (b.Contains(">")) {
b = b.Replace(">", "");
if (a >Convert.ToInt32(b))
{
Console.WriteLine("value is less");
}
else
{
Console.WriteLine("value is Greater");
}
}
similarly all the symbols
First separate symbol from b:
string symbol = b[0].ToString();
string numberString = b.SubString(1);
int number = int.Parse(numberString);
Now use switch to get operation for symbol and compare:
bool result = false;
switch (symbol)
{
case ">":
if (a > number)
{
result = true;
}
break;
}
EDIT: Changed symbol declaration to avoid error: "cannot implicit convert type char to string"
Lets say i have
int a = 1;
int b = 2;
string exp = "b > a";
and i want to evaluate the string expression with those variables
if(exp.SomeKindOfParseOrCast())
{
//here be magic
}
Is it possible in any simple way?
Nope, not in C# - these are parameter names, and thus are compile time values, and this expression parsing you are describing is done in runtime - the computer doesn't know the name of the parameters while it's being evaluated. Instead, you could do something a little more strict, like an expression parser - implement your own way to parse string expressions.
Very very simplified:
if(exp.Equals("b > a"))
{
if(b>a)
// do what you do if b is bigger than a
else
// do what you do with a wrong expression
}
else if (exp.Equals("a > b")
{
if(a>b)
// do what you do if a is bigger than b
else
// do what you do with a wrong expression
}
else if (exp.Equals("a = b")
{
if(a==b)
// do what you do if a is equal to b
else
// do what you do with a wrong expression
}
else
// do what you do with a badly formatted expression
if you would like to take this a step forward, you can cut spaces, make sure the expression is lowercase, etc. - there's many examples around, I personally like this one.
Is it possible in any simple way?
No, in C# this is not possible in a simple way like it were in languages such as JavaScript with its eval function. Anyway, you'd have to provide bindings of in-expression parameters to actual values.
You can use Roslyn.
Here is an example of how to compile and run your own code in runtime.
Disclaimer: I'm the owner of the project Eval Expression.NET
This library is very easy to use and allow to evaluate and compile almost all the C# language.
// For single evaluation
var value1 = Eval.Execute<bool>("b > a", new { a = 1, b = 2 });
// For many evaluation
var compiled = Eval.Compile<Func<int, int, bool>>("b > a", "a", "b");
var value2 = compiled(1, 2);
Let say, * has to be followed by &.
For example,
string asd = "Mother*&Mother*&Son";
// which is "Mother+ "*&" + "Mother" + "*&" + "Son"
// This is correct string.
Bad example,
string asd = "Mother*Mother*&Son";
string asf = "Mother**&Mother*&Son";
string asg = "Mother*&*Mother*&Son";
How can I check if the string is correct or not in C#?
EDIT
based on the usage of Regex that you guys introduced, I have a side question. I am actually using comma(,) instead of asterisk(*) and quotation mark(") instead of ampersand(&).
In C#, (Let me use one of the guy's example)
Regex.IsMatch("Mother,\",Mother,\"Son", #"\,(?!")")
//won't work.. any idea?
I also tried
Regex.IsMatch("Mother,\",Mother,\"Son", #"\,(?!\")")
//not work, neither
Find failures by looking for any asterisk (*) not followed by an ampersand (&):
Regex.IsMatch("Mother*&*Mother*&Son", #"\*(?!&)")
You can use regex. But it will be easier to find when string is not correct and then just negate the result.
I would look for any * which is not followed by &. The regex should look like: (\*[^&])|(\*$)
Simple test code:
var inputs = new[] {
"Mother*&Mother*&Son",
"Mother*Mother*&Son",
"Mother**&Mother*&Son",
"Mother*&*Mother*&Son",
"Mother*&Mother*&Son*"
};
var regex = new Regex(#"(\*[^&])|(\*$)");
var isOK = inputs.Select(x => !regex.IsMatch(x)).ToList();
Returns a list of results, which contains true, false, false, false, false.
For something like this, I'd favor the direct approach, rather than using Regex. This will make at most one pass through the entire string, which should be more efficient than a Regex.
/// Return true if every instance of 'a' in the string is followed by 'b'.
/// Also returns true if there are no instances of 'a' in the string.
/// Returns false if there exists any 'a' that is not followed by 'b'.
public static bool IsTwoCharSequence(string s, char a, char b)
{
if(String.IsNullOrEmpty(s)) return true;
if(s[s.Length - 1] == a) return false; // ends in a, not followed by b. Condition failed.
int index = s.IndexOf(a); // find the first a
while(index != -1)
{
if(s[index + 1] != b) return false; // a not followed by b.
index = s.IndexOf(a, index + 1);
}
return true; // either no a, or all a followed by b.
}
Edit: In addition, you don't need to worry about how to quote your separator characters, when they're also special characters within a Regex.
Edit 2: Yes, it's two loops, but look at what each loop is doing.
The inner loop, the one inside of String.IndexOf, will iterate through characters until it finds the passed-in character. The first call to IndexOf (the one outside the while loop) starts searching at the beginning of the string, and the subsequent ones start at that index, and continue searching to the next match, or to the end. Overall, we've made just one pass over the entire string.
Here's another method, which is similar in concept to the above one, but where the 'iterate the entire string only once' is more explicit.
public static bool IsTwoCharSequence(string s, char a, char b)
{
if (String.IsNullOrEmpty(s)) return true;
bool foundA = false;
foreach (char c in s)
{
if (foundA && c == b)
foundA = false;
else if (foundA)
return false;
else if (c == a)
foundA = true;
}
if (foundA) return false; // 'a' was the last char in the string.
return true;
}
Use Regular expressions and check that the number of matches for *& is the same as the number of *s
code of the top of my head, may not compile but try:
Regex r = new Regex(#"\*&");
Regex r2 = new Regex(#"\*");
if (r.Matches(myString).Count == r2.Matches(myString).Count) //success!
Good Morning,
In an if statement if we want to check if a string contains a value, we have :
if (string.Contains("Value1"))
{
}
How can we make the string compare with more values in an if statement without keep writing the whole statement? For example to avoid the below statement
if ((string.Contains("Value1") && (string.Contains("Value2")) && (string.Contains("Value3")))
{
}
Thank you
So, basically, you want to check if all of your values are contained in the string . Fortunately (with the help of LINQ), this can by translated almost literally into C#:
var values = new String[] {"Value1", "Value2", "Value3"};
if (values.All(v => myString.Contains(v))) {
...
}
Similarly, if you want to check if any value is contained in the string, you'd substitute All by Any.
Well, you could use LINQ:
string[] requiredContents = { "Foo", "Bar", "Baz" };
if (requiredContents.All(x => text.Contains(x))
{
...
}
Note that just like the short-circuiting && operator, All will stop as soon as it finds a value which doesn't satisfy the condition. (If you want to use Any in a similar way elsewhere, that will stop as soon as it finds a value which does satisfy the condition.)
I wouldn't bother for only a reasonably small number though. Without the extraneous brackets, it's really not that bad:
if (text.Contains("foo") && text.Contains("bar") && text.Contains("Baz"))
{
}
I would only start using the more general form if either there were genuinely quite a few values (I'd probably draw the line at about 5) or if the set of values was being passed in as a parameter, or varied in some other way.
As you need "your" string to contains all values:
var values = new String[] {"Value1", "Value2", "Value3"};
var s = yourString;
if (values.Count(v => s.Contains(v)) == values.Length) {
...
}
Is this the best solution? Probably not. Is it readable and extendable? Yes.
var matches = {"string1", "string2", "string3","string-n"};
var i = 0;
foreach(string s in matches)
{
if(mystring.Contains(s))
{
i++;
}
}
if(i == matches.Length)
{
//string contains all matches.
}
if(stringArray.Any(s => stringToCheck.Contains(s)))
If you want to ensure that it contains all the substrings, change Any to All:
if(stringArray.All(s => stringToCheck.Contains(s)))