Is there any better way to compare these values in C#? - c#

I have method for comparing values like this:
protected bool CompareValues(string a="", int b=0, string c="", int d=0, string e="", int f=0)
{
int counter = 0;
if(int.Parse(a) > b)
{
counter++;
}
if(int.Parse(c) > d)
{
counter++;
}
if(counter > 1)
{
counter = 1;
}
if(int.Parse(e) > f)
{
counter++;
}
if(counter > 1)
{
return true;
}
else
{
return false;
}
}
It works fine for me, but I am can't stand without thinking about some improvement if possible. Any suggestion would be appreciate.

If you need to perform n-many comparisons of the form
(int.Parse(a1) > b1 || int.Parse(a2) > b2 || ... || int.Parse(aK) > bK) && int.Parse(aN) > bN
You can make a method that just accepts a set of pairs of values to compare
protected bool CompareValues(params Tuple<string, int>[] comparisons)
{
if(ReferenceEquals(comparisons, null))
{
throw new ArgumentNullException("comparisons");
}
if(comparisons.Length < 1)
{
throw new ArgumentException("At least one pair to compare must be specified");
}
var atLeastOneComparisonSucceeded = comparisons.Length == 1;
for(var i = 0; !atLeastOneComparisonSucceeded && i < comparisons.Length - 1; ++i)
{
atLeastOneComparisonSucceeded = int.Parse(comparisons[i].Item1) > comparisons[i].Item2;
}
var lastIndex = comparisons.Length - 1;
return atLeastOneComparisonSucceeded && int.Parse(comparisons[lastIndex].Item1) > comparisons[lastIndex].Item2;
}
Usage:
var result = CompareValues(new Tuple<string, int>("5", 2),
new Tuple<string, int>("3", 1),
new Tuple<string, int>("1", 2));
If you only ever need 3 pairs of values (as in your original post), you could provide overloads for the method that provided appropriate default values, like this
protected static bool CompareValues(string a, int b)
{
return CompareValues(a, b, "1", 0);
}
protected static bool CompareValues(string a, int b, string c, int d)
{
return CompareValues(a, b, c, d, "1", 0);
}
protected static bool CompareValues(string a, int b, string c, int d, string e, int f)
{
return ((int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f);
}
Of course, the arguments passed down from the overloads must be chosen such that the semantics are appropriate.

I am not sure in the middle why you reset counter to 1, however this is what I understood
if((int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f)
{
return true;
}
else
{
return false;
}

It looks like you want:
return (int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f;

I'm not sure but is this what you are trying to do?
return ( ( int.Parse(a) > b || int.Parse(c) > d ) && int.Parse(e) > f);

Related

Quick Sort using C#

Hello I trying to do a QuickSort but didn't appear the result, For example the user input "cdabe" so the expected result is "abcde". May I know what is the cause why the result didn't display?
because There is no error in the code. I'm using MVC. My MergeSort is working properly but my QuickSort didn't.
Model :
public string QuickSort()
{
string arrangedSort = "";
string Word= "cdabe";
List<string> ListLetters = new List<string>();
for (int i = 0; i < Word.Length; i++)
{
ListLetters.Add(Word.Substring(i, 1));
}
aQuicksort(Word, 0, ListLetters.Count - 1);
void aQuicksort(string Word, int left, int right)
{
int i = left;
int j = right;
var pivot = Word[(left + right) / 2];
while (i <= j)
{
while (char.Parse(ListLetters[i]) < pivot)
i++;
while (char.Parse(ListLetters[i]) > pivot)
j--;
if (i <= j)
{
var tmp = ListLetters[i];
ListLetters[i] = ListLetters[j];
ListLetters[j] = tmp;
i++;
j--;
}
}
if (left < j)
aQuicksort(Word, left, j);
if (i < right)
aQuicksort(Word, i, right);
foreach (var listLetter in ListLetters)
{
arrangedSort += listLetter;
}
}
return arrangedSort;
}
Try this implementation, it uses LinQ using System.linq
public static IEnumerable<int> QSort3(IEnumerable<int> source)
{
if (!source.Any())
return source;
int first = source.First();
QSort3Helper myHelper =
source.GroupBy(i => i.CompareTo(first))
.Aggregate(new QSort3Helper(), (a, g) =>
{
if (g.Key == 0)
a.Same = g;
else if (g.Key == -1)
a.Less = g;
else if (g.Key == 1)
a.More = g;
return a;
});
IEnumerable<int> myResult = Enumerable.Empty<int>();
if (myHelper.Less != null)
myResult = myResult.Concat(QSort3(myHelper.Less));
if (myHelper.Same != null)
myResult = myResult.Concat(myHelper.Same);
if (myHelper.More != null)
myResult = myResult.Concat(QSort3(myHelper.More));
return myResult;
}
public class QSort3Helper
{
public IEnumerable<int> Less;
public IEnumerable<int> Same;
public IEnumerable<int> More;
}
code from this post

Check if at least one object is not zero

This function need to check that a=b=c=0 or only one is <>0
there is a best way to do this check?
void (int p, int a, int s) {
if ((p != 0 && a != 0)
|| (p != 0 && s != 0)
|| (a != 0 && s != 0)
|| (a != 0 && s != 0 && p != 0)) throw new Exception("Error please set A or P or S");
}
A simple solution, without using Linq or any of the overhead that comes with it:
public void Check(int p, int a, int s)
{
var count = 0;
if (p != 0) count++;
if (a != 0) count++;
if (s != 0) count++;
if (count >= 2)
Console.WriteLine("Please set only A or P or S or none");
else
Console.WriteLine("OK");
}
Working Fiddle: https://dotnetfiddle.net/ViMmRV
This function need to check that a=b=c=0 or only one <> 0
If I correctly understand that:
private void CheckValues(int p, int a, int s)
{
var values = new[] { p, a, s };
if (values.Sum() == 0 || values.Count(v => v != 0) == 1)
Console.WriteLine("Error");
else
Console.WriteLine("OK");
}
Or
private void CheckValues(params int[] values)
{
if (values.Sum() == 0 || values.Count(v => v != 0) == 1)
Console.WriteLine("Error");
else
Console.WriteLine("OK");
}
Thus:
CheckValues(0, 0, 0); // <- Error
CheckValues(0, 0, 1); // <- Error
CheckValues(0, 1, 2); // <- OK
CheckValues(1, 2, 3); // <- OK
void Method(int p, int a, int s)
{
if (new [] { p, a, s }.Count(i => i == 0) <= 1)
{
throw new Exception("Error please set A or P or S");
}
}

Sorting issue in .NET

I am using this linq query to sort a string column but the results I am getting does not seems to be in right order?
Query:
userList = users.OrderBy(u => u.FirstName)
.Skip(offset)
.Take(rowcount)
.ToList<User>();
Result:
rama &
11Rama
15rama
1Rama
2Rama
490110rama
IU-Rama
Rama
it should be something like?
1Rama
2Rama
11Rama
15rama
490110rama
IU-Rama
rama &
Rama
You are getting your result sorted by the code points of the characters and that is by far the most common implementation for sorting strings. What you are expecting is called natural sort order, see for example this article, but you will have to do it on your own because .NET does not provide this out of the box.
By adding this code you will be able to sort as you need it to be done. But this sorting will be done on client side and all records must be fetch as list.
userList = users.ToList<User>()
.OrderBy(u => u.FirstName,new NumericComparer())
.Skip(offset)
.Take(rowcount)
.ToList<User>();
public class NumericComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return StringLogicalComparer.Compare(x, y);
}
}
public class StringLogicalComparer
{
public static int Compare(string s1, string s2)
{
//get rid of special cases
if ((s1 == null) && (s2 == null)) return 0;
if (s1 == null) return -1;
if (s2 == null) return 1;
if ((s1.Equals(string.Empty) && (s2.Equals(string.Empty)))) return 0;
if (s1.Equals(string.Empty)) return -1;
if (s2.Equals(string.Empty)) return -1;
//WE style, special case
bool sp1 = Char.IsLetterOrDigit(s1, 0);
bool sp2 = Char.IsLetterOrDigit(s2, 0);
if (sp1 && !sp2) return 1;
if (!sp1 && sp2) return -1;
int i1 = 0, i2 = 0; //current index
while (true)
{
bool c1 = Char.IsDigit(s1, i1);
bool c2 = Char.IsDigit(s2, i2);
int r; // temp result
if (!c1 && !c2)
{
bool letter1 = Char.IsLetter(s1, i1);
bool letter2 = Char.IsLetter(s2, i2);
if ((letter1 && letter2) || (!letter1 && !letter2))
{
r = letter1 ? Char.ToLower(s1[i1]).CompareTo(Char.ToLower(s2[i2])) : s1[i1].CompareTo(s2[i2]);
if (r != 0) return r;
}
else if (!letter1) return -1;
else return 1;
}
else if (c1 && c2)
{
r = CompareNum(s1, ref i1, s2, ref i2);
if (r != 0) return r;
}
else if (c1)
{
return -1;
}
else
{
return 1;
}
i1++;
i2++;
if ((i1 >= s1.Length) && (i2 >= s2.Length))
{
return 0;
}
if (i1 >= s1.Length)
{
return -1;
}
if (i2 >= s2.Length)
{
return -1;
}
}
}
private static int CompareNum(string s1, ref int i1, string s2, ref int i2)
{
int nzStart1 = i1, nzStart2 = i2; // nz = non zero
int end1 = i1, end2 = i2;
ScanNumEnd(s1, i1, ref end1, ref nzStart1);
ScanNumEnd(s2, i2, ref end2, ref nzStart2);
int start1 = i1; i1 = end1 - 1;
int start2 = i2; i2 = end2 - 1;
int nzLength1 = end1 - nzStart1;
int nzLength2 = end2 - nzStart2;
if (nzLength1 < nzLength2) return -1;
if (nzLength1 > nzLength2) return 1;
for (int j1 = nzStart1, j2 = nzStart2; j1 <= i1; j1++, j2++)
{
int r = s1[j1].CompareTo(s2[j2]);
if (r != 0) return r;
}
// the nz parts are equal
int length1 = end1 - start1;
int length2 = end2 - start2;
if (length1 == length2) return 0;
if (length1 > length2) return -1;
return 1;
}
private static void ScanNumEnd(string s, int start, ref int end, ref int nzStart)
{
nzStart = start;
end = start;
bool countZeros = true;
while (Char.IsDigit(s, end))
{
if (countZeros && s[end].Equals('0'))
{
nzStart++;
}
else countZeros = false;
end++;
if (end >= s.Length) break;
}
}
}
Creating a custom IComparer would work for you.
Check this implementation: http://zootfroot.blogspot.com/2009/09/natural-sort-compare-with-linq-orderby.html
You code would then call myLinqQuery.OrderBy(item => item.sortProperty, new MyComparer<string>())
In his example, the sort order return:
image1.jpg
image4.jpg
image30.jpg
image200.jpg

How to make an incremental dynamic code that contains alphabets and numerics

My initial code is 'A0AA' and I need a code/function in C# that will increment it until it goes to 'Z9ZZ'.
for example.
first code is 'D9ZZ'
the next code should be 'E0AA'
sorry maybe my example is quite confusing.. here's another example.. thanks.
first code is 'D9AZ'
the next code should be 'D9BA'
string start = "A9ZZ";
int add = 1;
string next = String.Concat(start.Reverse().Select((x,i) =>
{
char first = i == 2 ? '0' : 'A';
char last = i == 2 ? '9' : 'Z';
if ((x += (char)add) > last)
{
return first;
}
else
{
add = 0;
return x;
}
})
.Reverse());
This should fix it.
private static IEnumerable<string> Increment(string value)
{
if (value.Length != 4)
throw new ArgumentException();
char[] next = value.ToCharArray();
while (new string(next) != "Z9ZZ")
{
next[3]++;
if (next[3] > 'Z')
{
next[3] = 'A';
next[2]++;
}
if (next[2] > 'Z')
{
next[2] = 'A';
next[1]++;
}
if (next[1] > '9')
{
next[1] = '0';
next[0]++;
}
yield return new string(next);
}
}
Example of calling this code:
IList<string> values = Increment("A0AA").Take(100).ToList();
foreach (var value in values)
{
Console.Write(value + " ");
}
Here's a pretty clean solution that checks every character starting at the end:
public SomeMethod()
{
var next = Increment("A2CZ"); // A2DZ
}
public string Increment(string code)
{
var arr = code.ToCharArray();
for (var i = arr.Length - 1; i >= 0; i--)
{
var c = arr[i];
if (c == 90 || c == 57)
continue;
arr[i]++;
return new string(arr);
}
return code;
}

C# build the if conditions at runtime

I have nested if else structure, more or less doing the same thing.
simply it's a single if(A && B && C)
but I have flag D and E for condition A and C respectively.
That means if D is false, A should be disappear and not evaluated. It's same for C not be evaluated if E if false.
Now, my code now is similar as follows:
if (D){
if (A && B){
if (E){
if (C)
{ Do Something }
} else { Do Something else}
}
} else
if (B) {
if (E){
if (C)
{ Do Something }
} else { Do Something else}
}
}
Is any easy way to reduce this complicated structure to several lines of code?
Since both branch actions are the same you could essentially write:
if ((D && A && B) || (!D && B))
{
if (E && C)
{
DoSomething();
}
else
{
DoSomethingElse();
}
}
Hopefully your variables are more readable than A,B,C etc :)
I have tested it in c since I am on unix console right now. However, logical operators work the same way for c#. following code can also be used to test the equivalance.
#include<stdio.h>
void test(int,int,int,int,int);
void test1(int,int,int,int,int);
int main()
{
for(int i =0 ; i < 2 ; i++)
for(int j =0 ; j < 2 ; j++)
for(int k =0 ; k < 2 ; k++)
for(int l =0 ; l < 2 ; l++)
for(int m =0 ; m < 2 ; m++)
{
printf("A=%d,B=%d,C=%d,D=%d,E=%d",i,j,k,l,m);
test(i,j,k,l,m);
test1(i,j,k,l,m);
printf("\n");
}
return 0;
}
void test1(int A, int B, int C, int D, int E)
{
if( B && (!D || A) && (!E || C))
{
printf("\n\ttrue considering flags");
}
else
{
printf("\n\tfalse considering flags");
}
}
void test(int A, int B, int C, int D, int E)
{
if(D)
{
if( A && B)
if(E)
if(C)
{
printf("\n\ttrue considering flags");
}
else
{
printf("\n\tAB !C DE");
}
}
else
{
if( B)
if(E)
if(C)
{
printf("\n\t!D --ignore A-- BC E");
}
else
{
printf("\n\tfalse considering flags");
}
}
}

Categories

Resources