OrderBy列表具有不同类型的值

时间:2014-01-21 03:39:33

标签: c# linq c#-4.0

我有多种类型的列表。像

这样的东西
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来对这样的列表进行排序。

4 个答案:

答案 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));