使用linq和自定义字符串要求对时间跨度进行排序

时间:2017-07-11 02:32:08

标签: c# linq

我有一个场景,我有一个时间表列表以及一个字符串字段,指示时间跨度是否应该在我所拥有的20个时间跨度的前16位。 例如:

BYVAL

我需要的是所有列表项目都有“自动”作为类型保留在前16位,无论排序后的时间如何。有时间(或其他值)的人可以低于第16项。

我想到的是用防止自动降到16以下的某种方法按时间对列表进行排序。然后我可以将17-20设置为替代。我根本不知道如何使用linq,我认为这将是最好的方式。

2 个答案:

答案 0 :(得分:1)

要控制类的排序方式,您可以使类实现IComparable或创建一个实现IComparer的单独类。

不同之处在于实现IComparable<T>指定了一个默认的排序顺序,如果有一些内在的,通常适用的明显排序顺序,这是有意义的。但在其他情况下,您可能有多种方法要对类进行排序。一个例子是.NET框架提供的各种StringComparer类。它们都是IComparer<string>的实现。

我没有上课,所以我编写了这个:

public class TimeSpanWithType
{
    public TimeSpan Time { get; set; }
    public string Type { get; set; }
}

这是一个比较器类,用类型&#34; auto&#34;对类进行排序。第一

public class AutoFirstComparer : IComparer<TimeSpanWithType>
{
    public int Compare(TimeSpanWithType x, TimeSpanWithType y)
    {
        if (x.Type!=y.Type)
        {
            if (x.Type == "auto") return -1;
            if (y.Type == "auto") return 1;
        }
        return x.Time.CompareTo(y.Time);
    }
}

为方便起见,这里是一个静态类,因此您不必继续创建比较器的新实例。

public static class TimeSpanWithTypeComparison
{
    public static IComparer<TimeSpanWithType> AutoFirst = new AutoFirstComparer();
}

这是一个单元测试,证明在排序时它会自动输出&#34;第一

[TestClass]
public class TimeSpanWithTypeComparisonTests
{
    [TestMethod]
    public void SortsAsExpected()
    {
        var time1 = new TimeSpanWithType() { Type = "xyz", Time = TimeSpan.FromHours(1) };
        var time2 = new TimeSpanWithType() { Type = "auto", Time = TimeSpan.FromHours(3) };
        var time3 = new TimeSpanWithType() { Type = "auto", Time = TimeSpan.FromHours(2) };
        var sorted = new TimeSpanWithType[] { time1, time2, time3 }
            .OrderBy(t => t, TimeSpanWithTypeComparison.AutoFirst).ToArray();
        Assert.AreEqual(sorted[0], time3);
        Assert.AreEqual(sorted[1], time2);
        Assert.AreEqual(sorted[2], time1);
    }
}

答案 1 :(得分:0)

这听起来像另一种说明问题的方式是:&#34;所有带有&#39; auto&#39;加上4个最快的没有&#39; auto&#39;&#34;。

var a = list.Where(x => x.Type == "auto").OrderBy(x => x.Time);
var b = list.Where(x => x.Type != "auto").OrderBy(x => x.Time).Take(4);
var result = a.Concat(b);