.NET一次迭代IEnumerable中的几个元素

时间:2013-11-17 21:15:38

标签: c# .net linq

给定一个集合,我需要一次遍历所有元素三(或其他一些数量)。例如:

string[] exampleData = {"John", "Doe", "1.1.1990", "Jane", "Roe", "2.2.1980"}

for(int i = 0; i < exampleData.Length; i += 3) {
    CreateUser(foreName: exampleData[i], surName: exampleData[i+1], dateOfBirth: exampleData[i+2]);
} 

如果exam​​pleData是IEnumerable而不是数组,我怎么能有效地重现这个?

6 个答案:

答案 0 :(得分:9)

有效的方法是使用扩展方法:

public static IEnumerable<IList<T>> ChunksOf<T>(this IEnumerable<T> sequence, int size)
{
    List<T> chunk = new List<T>(size);

    foreach (T element in sequence)
    {
        chunk.Add(element);
        if (chunk.Count == size)
        {
            yield return chunk;
            chunk = new List<T>(size);
        }
    }
}

您可以像这样使用它:

foreach (IList<string> chunk in exampleData.ChunksOf(3))
{
    CreateUser(foreName: chunk[0], surName: chunk[1], dateOfBirth: chunk[2]);
}

请注意,如果sequence.Count()不是size的整数倍,则ChunksOf会丢弃最后一个部分块。如果你想要返回一个部分块,你可以添加到最后:if (chunk.Count > 0) yield return chunk;

答案 1 :(得分:4)

此代码段将您的数组分组为3个元素的集合,然后为每个集合创建一个用户。

    exampleData.Select((elem, index) => new {elem, index})
        .GroupBy(x => x.index/3)
        .Select(x => CreateUser(
                          x.ElementAt(0).elem,
                          x.ElementAt(1).elem,
                          x.ElementAt(2).elem));

当然,您需要确保数组的长度是3的倍数。

答案 2 :(得分:1)

虽然我更喜欢迈克尔的方法,但如果你需要特定领域的解析(例如DOB解析),你可能更喜欢更具体的东西

public static IEnumerable<User> ExtractUsers(IEnumerable<string> input)
{
    int i = 0;
    string forename;
    string surname;
    string dateofbirth;
    foreach (string current in input) 
    {
        switch (i) 
        {
        case 0:
            one = forename;
            break;
        case 1:
            two = surname;
            break;
        case 2:
            three = dateofbirth;
            i = -1; //uck, this will get incremented at the bottom
            yield return CreateUser(forename, surname, dateofbirth);
            break;
        }
        i++;
    }
}

答案 3 :(得分:0)

Take()Skip()会做你想要的,但我会建议你避免使用这样的数组。您最好使用PersonFirstNameLastName属性创建DateOfBirth课程并保留其中的数组。

答案 4 :(得分:0)

如何忘记foreach,花哨的linq东西,临时的子列表等,并回到根源? : - )

调用.GetEnumerator()并在迭代中调用.MoveNext()三次。这就是枚举的核心。

以前的答案对我来说似乎过于复杂。这很简单和硬核: - )。

答案 5 :(得分:0)

您可以使用LINQ

        string[] exampleData = {"John", "Doe", "1.1.1990", "Jane", "Roe", "2.2.1980"};

        int chunkSize = 3;
        var seqences = from seqIndex in Enumerable.Range(0, exampleData.Length)
                       group exampleData[seqIndex] by seqIndex / chunkSize;
        foreach (var sub in seqences)
        {
            CreateUser(sub.ToList()[0], sub.ToList()[1], sub.ToList()[2]);
        }

编辑:

     var seqences = from m in Enumerable.Range(0, exampleData.Count()) group 
                           exampleData.ToList()[m] by m / chunkSize;

        int chunkSize = 3;
        var seqences = Enumerable.Range(0, exampleData.Count())
                       .GroupBy(m => m/chunkSize, m => exampleData.ToList()[m]);