List<T>的自定义排序

3
我有一个包含Event类型的List<T>,其中T是我的类型,并且具有类型为longtime字段。这个列表是从Web服务填充的,如果一个事件没有时间,则设置的值为0。
我想要做的是按时间升序排序我的列表,但将时间等于0的项目放在最底部。
目前我是以一种hack的方式实现这个功能的,我想学习更好的方式。
var events = new ObservableCollection<Event>();
var resp = JsonConvert.DeserializeObject<Events>(restResponse.Content).Items;

var notime = resp.Where(r => r.time == 0);
var yestime = resp.Where(r => r.time > 0);

yestime.ToList().ForEach(events.Add);
notime.ToList().ForEach(events.Add);

CallbackInternal(callback, events);

我尝试实现一个自定义的IComparer,但效果不太好(这里是我的一次尝试)

public class EventComparer : IComparer<Event>
{
    public int Compare(Event x, Event y)
    {
        if (x.time == 0) return 0;
        if (x.time < y.time) return -1;
        if (x.time > y.time) return 1;
        return 0;
    }
}

guidance is appreciated!

thanks!

5个回答

11
尝试一下。
   events.OrderBy (e => e.Time == 0).ThenBy (e => e.Time);

这是最佳解决方案。布尔值也可以排序! - usr

2

You could use LINQ:

resp.OrderBy(i => i.time == 0 ? int.MaxValue : i.time);

我尝试过类似的东西,但是我的逻辑不对。现在一切都变得清晰明了 :) - earthling

1
你应该像这样做:
 if(x.time==y.time) return 0;
 if(x.time==0) return 1;
 return x.time - y.time;

这里的重点是0比任何其他时间都要大,因此它将被放置在列表的末尾。

谢谢,我似乎无法清楚地思考这个问题。这有所帮助! - earthling

1

你的自定义 IComparer 有误。如果逻辑正确,它应该能正常工作。问题在于如果左值为零,则任何值都等于它。这意味着 0 == 3 是真的,而且 3 > 0 也是真的。事实上,0 > 33 < 0 应该是真的。

你应该像这样做:

if (x.time == y.time) return 0;
if (x.time == 0) return 1;
if (y.time == 0) return -1;
return x.time.CompareTo(y.time);

1

试试这个(你需要根据自己的需求进行调整):

    class Comparer : IComparer<int>
    {
        public int Compare(int x, int y)
        {
            if (x == y) return 0;
            else if (x == 0) return 1;
            else if (y == 0) return -1;
            else if (x < y) return -1;
            else if (x > y) return 1;
        }
    }

这个问题出在.Compare(0, 0)上,本应返回0,但实际返回了1 - phoog
编译器肯定不需要这些else,但是如果比较逻辑上相连,我通常会留下这些多余的else。在我看来,这样可以使代码更易读(特别是在最终返回之前有更多指令的情况下)。另一个方面是缺少最后一个else(和返回),但是控制永远不会到达那个点,因为所有其他选项都会在此之前用尽。但是一些编译器可能会抱怨。 - Spook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接