对多种数据类型的对象列表进行排序
Sorting a list of objects of multiple data types
我的代码中有这个 class
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;
}
}
在另一个 class 中,我想创建一个冒泡排序来对传递给它的股票列表 (List<Stocks>
) 进行排序,我对此有多个问题,主要问题是数据类型,当它们可能是 string
、int
、double
或 DateTime
时,比较两个值并不容易。我已经使用 TryParse
检查有效数据类型的方法完成了它,但我正在寻找一个很好的干净解决方案,这是我迄今为止的尝试
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*/ }
}
}
传递给它的 int
决定是否排序,这就是我使用反射的原因,因此变量可以通过数字访问。
- 日期
- 天
- 打开
- 关闭
- 差异
- 音量
为什么要自己实现排序?查看 IComparable
编辑:
将要排序的字段传递到方法中而无需反射的一种不错且类型安全的方法是:
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*/
}
}
您不应假设 GetFields
返回的字段将按特定顺序排列。
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.
一种选择是使用lambdas like LINQ's OrderBy
方法。使用泛型类型还可以让您的代码更易于重用,并让您的 Compare
方法更简单。
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);
我的代码中有这个 class
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;
}
}
在另一个 class 中,我想创建一个冒泡排序来对传递给它的股票列表 (List<Stocks>
) 进行排序,我对此有多个问题,主要问题是数据类型,当它们可能是 string
、int
、double
或 DateTime
时,比较两个值并不容易。我已经使用 TryParse
检查有效数据类型的方法完成了它,但我正在寻找一个很好的干净解决方案,这是我迄今为止的尝试
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*/ }
}
}
传递给它的 int
决定是否排序,这就是我使用反射的原因,因此变量可以通过数字访问。
- 日期
- 天
- 打开
- 关闭
- 差异
- 音量
为什么要自己实现排序?查看 IComparable
编辑:
将要排序的字段传递到方法中而无需反射的一种不错且类型安全的方法是:
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*/
}
}
您不应假设 GetFields
返回的字段将按特定顺序排列。
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.
一种选择是使用lambdas like LINQ's OrderBy
方法。使用泛型类型还可以让您的代码更易于重用,并让您的 Compare
方法更简单。
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);