how to compare attribute values including comparison operators in C# - c#

I am comparing two XML nodes which includes numeric values with comparison operators as shown below
<rule id="rule1" subject="user1" age="60" permission="granted"/>
<rule id="rule2" subject="user1" age=">=50" permission="denied"/>
This is a very simple example where the rule1 states that if the subject is user1 then the permission is granted if his age is 60 whereas the rule2 states that permission is denied for user1 if age is 50 or greater than 50. So it mean these rules are contradictory.
My question is that how could I compare the age attribute which is including numeric values and comparison operators. In the above example I conclude that both the rules have contradictory values.
I am using C# to compare these attribute values.

I would create a syntax tree from xml and use the tree to evaluate the conditions. As for how to evaluate comparison-based rule, you can write your own class like:
public enum BinaryOperator
{
LessThenOrEqual,
LessThen,
Equal,
GreaterThen,
GreaterThenOrEqual
}
public class BinaryOperatorEvaluator
{
public BinaryOperatorEvaluator(BinaryOperator op)
{
Operator = op;
}
public BinaryOperator Operator { get; private set; }
public bool Evaluate(IComparable x, IComparable y)
{
switch (Operator)
{
case BinaryOperator.Equal:
return x.CompareTo(y) == 0;
case BinaryOperator.GreaterThen:
return x.CompareTo(y) > 0;
case BinaryOperator.GreaterThenOrEqual:
return x.CompareTo(y) >= 0;
case BinaryOperator.LessThen:
return x.CompareTo(y) < 0;
case BinaryOperator.LessThenOrEqual:
return x.CompareTo(y) <= 0;
default:
throw new NotImplementedException();
}
}
public static BinaryOperatorEvaluator FromExpression(string expression, out int value)
{
var regexValidTerm = new Regex("^(?<operator>(<=|=|>=|<|>)?)(?<numeric>([0-9]+))$");
var match = regexValidTerm.Match(expression);
if (!match.Success)
{
throw new ArgumentException("Not a valid expression.", "expression");
}
var opValue = match.Groups["operator"].Value;
var op = BinaryOperator.Equal;
if (!string.IsNullOrEmpty(opValue))
{
switch(opValue)
{
case "<=":
op = BinaryOperator.LessThenOrEqual;
break;
case "=":
op = BinaryOperator.Equal;
break;
case ">=":
op = BinaryOperator.GreaterThenOrEqual;
break;
case "<":
op = BinaryOperator.LessThen;
break;
case ">":
op = BinaryOperator.LessThenOrEqual;
break;
default:
throw new NotImplementedException();
}
}
value = int.Parse(match.Groups["numeric"].Value);
return new BinaryOperatorEvaluator(op);
}
}
int number;
var bo = BinaryOperatorEvaluator.FromExpression("<=15", out number);
// false
var foo = bo.Evaluate(16, number);
// true
foo = bo.Evaluate(15, number);
// also true
foo = bo.Evaluate(14, number);

Add the runat="server" inside your tags, then access the attribute with rule1.Attributes["age"] within c# code. And overload operator for comparison if its logic requires this.

You might consider doing this in code behind, makes it a heck lot easier.
if(age > 50)
permission = "denied";
else if(age == 60)
permission = "granted";

Related

Math Comparison on 2 Numbers with Multiple Decimals

I need to compare section numbers in a document, at first I was just going to convert to decimal and check to see if one number is greater than another.
The issue there is that some sections have multiple decimals.
Example: I need to perform a math comparison on 1.1 with 1.1.2.3 to determine which one is farther along in a document.
They are strings to begin with and I need to do some math comparisons on them essentially.
I though about removing the decimals then converting to int but this throws off certain sections, like section 2 would be considered less than section 1.1 since 1.1 would be changed to a 11, which is no good.
string section1 = "1.1";
string section2 = "2";
int convertedSection1 = Convert.ToInt32(section1.Replace(".",""));
int convertedSection2 = Convert.ToInt32(section2.Replace(".",""));
if(convertedSection1 < convertedSection2)
//This will incorrectly say 1.1 is greater than 2
string section1 = "1.1.2.4";
string section2 = "2.4";
decimal convertedSection1 = Convert.ToDecimal(section1);
decimal convertedSection2 = Convert.ToDecimal(section2);
if(convertedSection1 < convertedSection2)
//This will convert 1.1.2.4 to 1.1 which is no good
You can create a class similar to the Version class of the .NET framework. If you implement some operators and IComparable, it's really nice.
How does it work? It will convert the given string into a list of integer numbers. Upon comparison, it will start at the beginning of each list and compare each individual part.
public class Section: IComparable<Section>
{
// Stores all individual components of the section
private List<int> parts = new List<int>();
// Construct a section from a string
public Section(string section)
{
var strings = section.Split('.');
foreach (var s in strings)
{
parts.Add(int.Parse(s));
}
}
// Make it nice for display
public override string ToString()
{
return string.Join(".", parts);
}
// Implement comparison operators for convenience
public static bool operator ==(Section a, Section b)
{
// Comparing the identical object
if (ReferenceEquals(a, b)) return true;
// One object is null and the other isn't
if ((object)a == null) return false;
if ((object)b == null) return false;
// Different amount of items
if (a.parts.Count != b.parts.Count) return false;
// Check all individual items
for (int i=0; i<a.parts.Count;i++)
{
if (a.parts[i] != b.parts[i]) return false;
}
return true;
}
public static bool operator !=(Section a, Section b)
{
return !(a == b);
}
public static bool operator <(Section a, Section b)
{
// Use minimum, otherwise we exceed the index
for (int i=0; i< Math.Min(a.parts.Count, b.parts.Count); i++)
{
if (a.parts[i] < b.parts[i]) return true;
}
if (b.parts.Count > a.parts.Count) return true;
return false;
}
public static bool operator >(Section a, Section b)
{
// Use minimum, otherwise we exceed the index
for (int i = 0; i < Math.Min(a.parts.Count, b.parts.Count); i++)
{
if (a.parts[i] > b.parts[i]) return true;
}
if (a.parts.Count > b.parts.Count) return true;
return false;
}
// Implement the IComparable interface for sorting
public int CompareTo(Section other)
{
if (this == other) return 0;
if (this < other) return -1;
return 1;
}
}
Tests for 96% coverage:
Assert.IsTrue(new Section("1.2.3.4") > new Section("1.2.3"));
Assert.IsFalse(new Section("1.2.3.4") < new Section("1.2.3"));
Assert.IsFalse(new Section("1.2.3.4") == new Section("1.2.3"));
Assert.IsTrue(new Section("1.2.3.4") == new Section("1.2.3.4"));
Assert.IsFalse(new Section("1.2.3.4") == new Section("1.2.3.5"));
Assert.IsTrue(new Section("1.2.3.4") != new Section("1.2.3.5"));
var sec = new Section("1");
Assert.IsTrue(sec == sec);
Assert.AreEqual("1.2.3.4", new Section("1.2.3.4").ToString());
var sortTest = new List<Section> { new Section("2"), new Section("1.2"), new Section("1"), new Section("3.1") };
sortTest.Sort();
var expected = new List<Section> { new Section("1"), new Section("1.2"), new Section("2"), new Section("3.1") };
CollectionAssert.AreEqual(expected, sortTest, new SectionComparer());
If you know that your section strings are always well formed, and you know that they don't go deeper than 6 levels, and that no level has more than 999 items, then this works nicely:
string zero = ".0.0.0.0.0.0";
long Section2Long(string section) =>
(section + zero)
.Split('.')
.Take(6)
.Select(t => long.Parse(t))
.Aggregate((x, y) => x * 1000 + y);
Now, if I have this:
string[] sections = new []
{
"1.2.4", "2.3", "1", "1.2", "1.1.1.1", "1.0.0.1.0.1", "2.2.9"
};
I can easily sort it like this:
string[] sorted = sections.OrderBy(x => Section2Long(x)).ToArray();
I get this output:
1
1.0.0.1.0.1
1.1.1.1
1.2
1.2.4
2.2.9
2.3

What's a good algorithm for checking if a given list of values alternates up and down?

Assuming the function takes in a list of double and an index to perform the check from, I need to check if the values alternates up and down consecutively.
For example, a list of [14.0,12.3,13.0,11.4] alternates consecutively but a list of [14.0,12.3,11.4,13.0] doesn't.
The algorithm doesn't have to be fast, but I'd like it to be compact to write (LINQ is totally fine). This is my current method, and it looks way too crude to my taste:
enum AlternatingDirection { Rise, Fall, None };
public bool CheckConsecutiveAlternation(List<double> dataList, int currDataIndex)
{
/*
* Result True : Fail
* Result False : Pass
*/
if (!_continuousRiseFallCheckBool)
return false;
if (dataList.Count < _continuousRiseFallValue)
return false;
if (currDataIndex + 1 < _continuousRiseFallValue)
return false;
AlternatingDirection direction = AlternatingDirection.None;
int startIndex = currDataIndex - _continuousRiseFallValue + 1;
double prevVal = 0;
for (int i = startIndex; i <= currDataIndex; i++)
{
if (i == startIndex)
{
prevVal = dataList[i];
continue;
}
if (prevVal > dataList[i])
{
prevVal = dataList[i];
switch (direction)
{
case AlternatingDirection.None:
direction = AlternatingDirection.Fall;
continue;
case AlternatingDirection.Rise:
direction = AlternatingDirection.Fall;
continue;
default:
//Two falls in a row. Not a signal.
return false;
}
}
if (prevVal < dataList[i])
{
prevVal = dataList[i];
switch (direction)
{
case AlternatingDirection.None:
direction = AlternatingDirection.Rise;
continue;
case AlternatingDirection.Fall:
direction = AlternatingDirection.Rise;
continue;
default:
//Two rise in a row. Not a signal.
return false;
}
}
return false;
}
//Alternated n times until here. Data is out of control.
return true;
}
Try this:
public static bool IsAlternating(double[] data)
{
var d = GetDerivative(data);
var signs = d.Select(val => Math.Sign(val));
bool isAlternating =
signs.Zip(signs.Skip(1), (a, b) => a != b).All(isAlt => isAlt);
return isAlternating;
}
private static IEnumerable<double> GetDerivative(double[] data)
{
var d = data.Zip(data.Skip(1), (a, b) => b - a);
return d;
}
Live demo
The idea is:
If the given list of values is alternating up and down, mathematically it means that it's derivative keeps changing its sign.
So this is exactly what this piece of code does:
Get the derivative.
Checks for sign fluctuations.
And the bonus is that it will not evaluate all of the derivative / signs arrays unless it is necessary.
I'd do it with a couple of consecutive zips, bundled in an extension method:
public static class AlternatingExtensions {
public static bool IsAlternating<T>(this IList<T> list) where T : IComparable<T>
{
var diffSigns = list.Zip(list.Skip(1), (a,b) => b.CompareTo(a));
var signChanges = diffSigns.Zip(diffSigns.Skip(1), (a,b) => a * b < 0);
return signChanges.All(s => s);
}
}
Edit: for completeness, here's how you'd use the feature:
var alternatingList = new List<double> { 14.0, 12.3, 13.0, 11.4 };
var nonAlternatingList = new List<double> { 14.0, 12.3, 11.4, 13.0 };
alternatingList.IsAlternating(); // true
nonAlternatingList.IsAlternating(); // false
I also changed the implementation to work on more types, making use of generics as much as possible.
Here is a small pseudo code. Assuming no repeated elements (can be handled easily though by few tweaks)
Idea is to have a sign variable which is alternating 1,-1,... that is multipled by the difference of two consecutive pairs, the difference multipled by this sign variable must always be positive. If it's not at some point, return false.
isUpAndDown(l):
if size(l) < 2: // empty,singleton list is always good.
return true
int sign = (l[0] < l[1] ? 1 : -1)
for i from 0 to n-1 (exclusive):
if sign * (l[i+1] - l[i]) < 0:
return false //not alternating
sign = sign * -1
end for
return true //all good
You may create kind of a signed array first:
double previous = 0;
var sign = myList.Select(x => {
int s = Math.Sign(x - previous);
previos = x;
return s;
});
This gives you a list similar to
{ -1, 1, -1, ... }
Now you can take a similar appraoch as the previos Select-statement to check if a -1 follows a 1:
var result = sign.All(x => {
bool b = x == -previous;
previous = x;
return b;
});
Now result is true if your list alternates, false otherwise.
EDIT: To ensure that the very first check within the second query also passes add previous = -sign[0]; before the second query.
Assuming that two equal values in a row are not acceptable (if they are, just skip over equal values):
if (dataList[0] == dataList[1])
return false;
bool nextMustRise = dataList[0] > dataList[1];
for (int i = 2; i < dataList.Count; i++) {
if (dataList[i - 1] == dataList[i] || (dataList[i - 1] < dataList[i]) != nextMustRise)
return false;
nextMustRise = !nextMustRise;
}
return true;
public double RatioOfAlternations(double[] dataList)
{
double Alternating = 0;
double Total = (dataList.Count()-2);
for (int (i) = 0; (i) < Total; (i)++)
{
if (((dataList[i+1]-dataList[i])*(dataList[i+2]-dataList[i+1]))<0)
// If previous change is opposite sign to current change, this will be negative
{
Alternating++;
}
else
{
}
}
return (Alternating/Total);
}

How to pass property as a parameter in order to use the same function to modify different properties

I've found similar questions asked before but the answers I've seen have been specific to the example given by the person or workarounds for that person's example, not a general solution.
I'd like to pass a class' property to a function to do an operation on that property. The example I'm going to use is incrementing a value, but I have more complicated scenarios so I'm looking for a general solution, not an answer for specifically incrementing.
How I used to do it is I'd either have multiple functions IncrementPassengerCount, IncrementDistanceTravelled, IncrementPlaneAge, but that's unweildly and horrible.
I'd like one general function that I can call using something like this pseudocode:
Increment(myPlane, myPlane.DistanceTravelled);
Increment(myPlane, myPlane.PlaneAge);
//where
public void Increment(Airplane myPlane, Property propToIncrement)
{
myPlane.propToIncrement++; //or do whatever like I now have myPlane.DistanceTravelled
}
I've tried this:
Increment(myPlane, x => x.DistanceTravelled);
//where
public void Increment(Airplane myPlane, Func<Log, IComparable> property)
{
property(myPlane)++;
}
But this causes a
Operator '++' cannot be applied to operand of type 'System.IComparable'
Is there a way to do what I'm imagining or am I looking at it wrong? Thanks in advance.
Is is possible, though convoluted and probably a sign that you should perhaps do it a different way, but here it is. (I would recommend as Jon Skeet mentioned, to just use the ++ operator instead of invoking the Increment method. In addition to the method I included two classes that will allow you to test the code in a console app. There would need to be plenty of error checking. I have a few null checks, but there may be more locations it is needed. If you have overloaded the ++ operator, it works for those types too, but any errors cannot be anticipated.
public static void Increment(this object o, string propertyName)
{
var property = o.GetType().GetProperty(propertyName);
if (property == null)
return;
var val = property.GetValue(o, null);
var op_Inc = o.GetType().GetMethod("op_Increment");
if(op_Inc != null)
{
var val2 = op_Inc.Invoke(val, null);
property.SetValue(o,val2);
}
switch (Type.GetTypeCode(property.PropertyType))
{
case TypeCode.UInt16:
{
var x = (UInt16)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.UInt32:
{
var x = (UInt32)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.UInt64:
{
var x = (UInt64)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Int16:
{
var x = (Int16)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Int32:
{
var x = (Int32)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Int64:
{
var x = (Int64)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Decimal:
{
var x = (Decimal)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Double:
{
var x = (Double)val;
x++;
property.SetValue(o, x);
}
break;
case TypeCode.Single:
{
var x = (Single)val;
x++;
property.SetValue(o, x);
}
break;
}
}
}
public class Example
{
public static void Main()
{
var plane = new Plane(){DistanceTravelled = 0, PlaneAge = 0};
Console.WriteLine("Before invoking increment: dist = {0}, age = {1}", plane.DistanceTravelled, plane.PlaneAge);
plane.Increment("DistanceTravelled");
plane.Increment("PlaneAge");
Console.WriteLine("After invoking increment: dist = {0}, age = {1}", plane.DistanceTravelled, plane.PlaneAge);
Console.ReadKey();
}
}
public class Plane
{
public int DistanceTravelled { get; set; }
public int PlaneAge { get; set; }
}

How to cast object to every number in a sorting of list-view?

I've taken the class to sort the lst view from msdn
I have got the type the column that i click so:
public int Compare(object x, object y)
{
int returnVal = new int();
// Determine whether the type being compared is a date type.
switch (field_type.Split('(')[0])
{
case "int":
case "float":
case "tinyiny":
case "smallint":
case "bigint":
case "bit":
case "mediumint":
case "double":
case "decimal":
case "unsigned":
returnVal = 0;
break;
// case "
case "date":
case "datetime":
// Parse the two objects passed as a parameter as a DateTime.
System.DateTime firstDate =
DateTime.Parse(((ListViewItem)x).SubItems[col].Text);
System.DateTime secondDate =
DateTime.Parse(((ListViewItem)y).SubItems[col].Text);
// Compare the two dates.
returnVal = DateTime.Compare(firstDate, secondDate);
break;
default: // Compare the two items as a string.
returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text);
break;
}
}
In case the column clicked is a number float,int,deciam ecc... how can i write one function that return the max between the 2 object?
Use the available CompareTo methods for the given type. E.g:
case "int":
returnValue = ((int) x).CompareTo((int) y);
public int Compare(object x, object y)
{
var a = x as IComparable ;
if (a == null) throw new Exception();
return a.CompareTo(y);
}

Why do "Not all code paths return a value" with a switch statement and an enum?

I have the following code:
public int Method(MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.Value1: return 1;
case MyEnum.Value2: return 2;
case MyEnum.Value3: return 3;
}
}
public enum MyEnum
{
Value1,
Value2,
Value3
}
And I get the error: "Not all code paths return a value". I do not understand how that switch statement could ever not jump to one of the specified cases.
Can an enum somehow be null?
There's nothing to say that the value of myEnum will be one of those values.
Don't mistake enums for being a restrictive set of values. It's really just a named set of values. For example, I could call your method with:
int x = Method((MyEnum) 127);
What would you want that to do? If you want it to throw an exception you can do that in a default case:
switch (myEnum)
{
case MyEnum.Value1: return 1;
case MyEnum.Value2: return 2;
case MyEnum.Value3: return 3;
default: throw new ArgumentOutOfRangeException();
}
Alternatively you could use Enum.IsDefined upfront, if you want to do some other work before the switch statement. That has the disadvantage of boxing... there are some ways round that, but they're generally more work...
Sample:
public int Method(MyEnum myEnum)
{
if (!IsDefined(typeof(MyEnum), myEnum)
{
throw new ArgumentOutOfRangeException(...);
}
// Adjust as necessary, e.g. by adding 1 or whatever
return (int) myEnum;
}
This assumes there's an obvious relationship between the underlying values in MyEnum and the value you want to return.
Enums are not limited to values they represent. You can assign this:
MyEnum v = (MyEnum)1000;
And there would be no problem at all. Add a default to your switch and you'll handle all possible situations.
If you change the values in your enum (adding a fourth) your code will break. You should add a default: case to your switch statement.
of course, the other way to achieve this would be to define the integer values in your enum...
public enum MyEnum
{
Value1 = 1,
Value2 = 2,
Value3 = 3
}
and then cast your enum as an int in code. Instead of int myInt = Method(myEnumValue); you can use int myInt = (int)myEnum
MyEnum blah = 0;
Default is always 0 and is implicitly convertible, even if you do not have one with a 0 value.
It has to be either:
public int Method(MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.Value1: return 1;
case MyEnum.Value2: return 2;
case MyEnum.Value3: return 3;
default: return 0;
}
}
or:
public int Method(MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.Value1: return 1;
case MyEnum.Value2: return 2;
case MyEnum.Value3: return 3;
}
return 0;
}

Categories

Resources