我想在我的项目中使用Linq来查询一个公交时刻表,这样在任何时候我都可以得到接下来的5个公交到达时间。如何将查询限制在前5个结果?

更一般地说,我如何在c#中获取一个列表的切片?(在Python中,我会使用mylist[:5]来获取前5个元素。)


当前回答

如果有人感兴趣(即使问题不要求这个版本),在c# 2中将是:(我已经编辑了答案,以下是一些建议)

myList.Sort(CLASS_FOR_COMPARER);
List<string> fiveElements = myList.GetRange(0, 5);

其他回答

var firstFiveItems = myList.Take(5);

或切:

var secondFiveItems = myList.Skip(5).Take(5);

当然,通常按照某种顺序获取前五项是很方便的:

var firstFiveArrivals = myList.OrderBy(i => i.ArrivalTime).Take(5);

如果有人感兴趣(即使问题不要求这个版本),在c# 2中将是:(我已经编辑了答案,以下是一些建议)

myList.Sort(CLASS_FOR_COMPARER);
List<string> fiveElements = myList.GetRange(0, 5);

我认为这是正确的答案,适用于从8.0开始的c#版本:

是的!它允许我们像在Python中一样工作。

来自c# 8.0文档:

c# 8.0特性规范:

该特性提供了两个新的操作符,允许构造System。索引和系统。Range对象,并在运行时使用它们来索引/切片集合。

c#将点字符(..)作为范围操作符

例子:

var array = new int[] { 1, 2, 3, 4, 5 };
var slice1 = array[2..^3];    // array[new Range(2, new Index(3, fromEnd: true))]
var slice2 = array[..^3];     // array[Range.EndAt(new Index(3, fromEnd: true))]
var slice3 = array[2..];      // array[Range.StartAt(2)]
var slice4 = array[..];       // array[Range.All]

要获得前5个元素,最好使用这样的表达式:

var firstfivearrival = myList.Where([表达式]).Take(5);

or

var firstfivearrival = myList.Where([表达式]). take(5)。OrderBy (EXPR)(命令);

它将比orderBy变体更快,因为LINQ引擎由于执行延迟而不会扫描所有列表,并且不会对所有数组进行排序。

class MyList : IEnumerable<int>
{

    int maxCount = 0;

    public int RequestCount
    {
        get;
        private set;
    }
    public MyList(int maxCount)
    {
        this.maxCount = maxCount;
    }
    public void Reset()
    {
        RequestCount = 0;
    }
    #region IEnumerable<int> Members

    public IEnumerator<int> GetEnumerator()
    {
        int i = 0;
        while (i < maxCount)
        {
            RequestCount++;
            yield return i++;
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    #endregion
}
class Program
{
    static void Main(string[] args)
    {
        var list = new MyList(15);
        list.Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 5;

        list.Reset();
        list.OrderBy(q => q).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 15;

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).OrderBy(q => q).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)
    }
}

工作的例子:

    [Test]
    public void TestListLinqTake()
    {
        List<string> elements = new List<string>() { "storm", "earth", "fire"};
        List<string> noErrorThrown = elements.Take(5).ToList();
        List<string> someElements = elements.Take(2).ToList();

        Assert.True(
            someElements.First().Equals("storm") &&
            someElements.Count == 2 &&
            noErrorThrown.Count == 3);
    }

不要忘记

using System.Linq;

根据Bellarmine Head的评论