我有多种类型的列表。像
这样的东西List<object> list = new List<object>() { 11.21, 323, 4, 3221, 221, 2, "asd" };
var qu = list.OrderBy((o) => o);
qu.ToList().ForEach((e) => Console.WriteLine(e)); // throws exception
抛出的异常是“对象必须是Int32类型。”
如何编写Linq来对这样的列表进行排序。
答案 0 :(得分:2)
List<object> list = new List<object>() { 11.21, 323, 4, 3221, 221, 2, "asd" };
var qu = list.OrderBy((o) => o.ToString());
qu.ToList().ForEach((e) => Console.WriteLine(e));
你必须将你的物品投射到某个东西上,而不一定是int。在这个例子中,我把所有东西都变成了字符串请记住,OrderBy操作将按字符串排序,当然不是数字排序。您无法按数字排序,因为列表中有一个字符串项。
答案 1 :(得分:2)
这是我写过的最疯狂的LINQ查询之一......
var qu = list.Select(x =>
{
decimal? d;
try
{
d = Convert.ToDecimal(x);
}
catch (FormatException)
{
d = null;
}
return new { v = x, d, s = x.ToString() };
}).GroupBy(x => x.d.HasValue)
.Select(g =>
g.Key
? g.OrderBy(x => x.d.Value).Select(x => x.v)
: g.OrderBy(x => x.s).Select(x => x.v))
.SelectMany(x => x)
.ToList();
首先返回所有数值(使用其值排序),然后使用标准字符串比较排序所有字符串。
答案 2 :(得分:1)
我会使用自定义比较器:
o = o.OrderBy(x => x, new MyComparer());
...
internal class CustomComparer : IComparer<object>
{
public int Compare(object x, object y)
{
if (x is string && y is string)
{
return ((string)x).CompareTo((string)y);
}
else if (x is string && IsNumber(y))
{
return -1;
}
else if (y is string && IsNumber(x))
{
return 1;
}
else if (IsNumber(x) && IsNumber(y))
{
return (Convert.ToDouble(x)).CompareTo(Convert.ToDouble(y));
}
else
{
throw new NotSupportedException();
}
}
private bool IsNumber(object o)
{
var t = o.GetType();
if (o is int || o is double || o is float || o is long)
return true;
return false;
}
}
答案 3 :(得分:0)
像这样实施IComparer<T>
怎么样?
public class MyComparer : IComparer<object>
{
public int Compare(object x, object y)
{
var type = x.GetType();
var type2 = y.GetType();
if (type == typeof(string) && type2 == typeof(string))
{
return String.Compare((string)x, (string)y);
}
else if (type.IsValueType && type2.IsValueType)
{
var comp = Comparer<double>.Default;
return comp.Compare(Convert.ToDouble(x), Convert.ToDouble(y));
}
else
{
return 0;
}
}
}
并使用它:
List<object> list = new List<object>() { 11.21, 323, 4, 3221, 221, 2, "asd" };
var qu = list.OrderBy(o => o, new MyComparer());
qu.ToList().ForEach((e) => Console.WriteLine(e));