Reputation: 109
I have this class in my code
class Stock
{
public DateTime Date;
public string Day;
public double Open, Close, Diff;
public int Volume;
public Stock(double open, double close, double diff, int volume, string day, DateTime date)
{
this.Open = open;
this.Close = close;
this.Diff = diff;
this.Volume = volume;
this.Day = day;
this.Date = date;
}
}
In another class i want to create a bubble sort that will sort a List of Stocks (List<Stocks>
) passed to it, i am having multiple issues with this the main problem is the data types, its not easy comparing two values when they could be a string
, int
, double
or DateTime
. I have done it with a method that uses TryParse
to check for valid data type, but im looking for a nice clean solution, this is my attempt so far
public void BubblesortBy(int sortBy, List<Stock> Stocks)
{
Type objType = typeof(Stock);
FieldInfo[] fields = objType.GetFields();
Stock temp = null;
int loopCount = 0;
bool doBreak = true;
for (int i = 0; i < Stocks.Count; i++)
{
doBreak = true;
for (int j = 0; j < Stocks.Count - 1; j++)
{
if (Compare(fields[sortBy - 1].FieldType.ToString(), fields[sortBy].GetValue(Stocks[j]), fields[sortBy].GetValue(Stocks[j+1])))
{
temp = Stocks[sortBy + 1];
Stocks[sortBy + 1] = Stocks[sortBy];
Stocks[sortBy] = temp;
doBreak = false;
}
loopCount++;
}
if (doBreak) { break; /*early escape*/ }
}
}
The int
passed to it determines whether to sort by, which is why i am using reflection so the variables are accessible by numbers.
Upvotes: 0
Views: 2126
Reputation: 56546
You shouldn't assume that the fields returned by GetFields
will be in a certain order.
The GetFields method does not return fields in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which fields are returned, because that order varies.
One option is to use lambdas like LINQ's OrderBy
method does. Using generic types can also make your code more reusable, and make things like your Compare
method simpler.
public void BubblesortBy<TSource, TKey>(Func<TSource, TKey> keySelector,
List<TSource> stocks)
{
int loopCount = 0;
bool doBreak = true;
for (int i = 0; i < stocks.Count; i++)
{
doBreak = true;
for (int j = 0; j < stocks.Count - 1; j++)
{
if (Compare(keySelector(stocks[j]), keySelector(stocks[j+1])))
{
TSource temp = stocks[j + 1];
stocks[j + 1] = stocks[j];
stocks[j] = temp;
doBreak = false;
}
loopCount++;
}
if (doBreak) { break; /*early escape*/ }
}
}
private bool Compare<T>(T l, T r)
{
return Comparer<T>.Default.Compare(l, r) > 0;
}
// use like
BubblesortBy(x => x.Close, myList);
Upvotes: 1
Reputation: 2737
Why are you implementing sorting yourself? Look into IComparable
Edit:
A nice and type safe way to pass the field to sort by into the method without refection, would be:
BubblesortBy(x => x.FieldName, stockes);
public void BubblesortBy<T>(Func<Product, T> sortBy, List<Stock> Stocks)
{
Stock temp = null;
int loopCount = 0;
bool doBreak = true;
for (int i = 0; i < Stocks.Count; i++)
{
doBreak = true;
for (int j = 0; j < Stocks.Count - 1; j++)
{
if (Compare(sortBy(Stocks[j]), sortBy(Stocks[j + 1])))
{
temp = Stocks[sortBy + 1];
Stocks[sortBy + 1] = Stocks[sortBy];
Stocks[sortBy] = temp;
doBreak = false;
}
loopCount++;
}
if (doBreak)
break; /*early escape*/
}
}
Upvotes: 1