Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个可枚举列表会分裂?_C#_Linq_Ienumerable - Fatal编程技术网

C# 为什么这个可枚举列表会分裂?

C# 为什么这个可枚举列表会分裂?,c#,linq,ienumerable,C#,Linq,Ienumerable,我试图从一个字符串列表中一次提取3行,但它没有按预期工作。考虑这个代码… var listOfStrings = new List<string> { "String 1", "String 2", "String 3", "String 4", "String 5", "String 6" }; foreach (var x in listOfStrings.Take(3).ToList()) { var currRows

我试图从一个字符串列表中一次提取3行,但它没有按预期工作。考虑这个代码…

var listOfStrings = new List<string>
{
    "String 1",
    "String 2",
    "String 3",
    "String 4",
    "String 5",
    "String 6"
};

foreach (var x in listOfStrings.Take(3).ToList())
{
    var currRows = x.ToList();

    // currRows should have 3 items
    foreach (var itm in currRows)
    {

    }
}
var listOfStrings=新列表
{
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”
};
foreach(listofstring.Take(3.ToList()中的变量x)
{
var currRows=x.ToList();
//Currows应该有3项
foreach(以当前行为单位的var itm)
{
}
}
第一次运行时,我希望currRows包含3项(字符串1、2和3),第二次运行时,我希望包含这3项(字符串4、5和6)。但是当我运行这个命令时,行只包含例如“string1”,这是一个字符一个字符分割的

我错过了什么

  • x.ToList()
    正在对
    字符串
    调用该方法。
    string
    是一个
    IEnumerable
    ,因此
    currows
    的结果是一个字符列表。您可以完全删除该行,并在第二个循环中使用
    x
  • 如果在
    foreach
    循环中使用的集合上使用
    ToList()
    通常是[1]一个无意义的操作。它将迭代您的集合并构造一个新列表,然后对其进行迭代。您可以从第一个循环中删除
    ToList
    ,它的性能会更好,但结果相同
  • Take
    只获取
    n
    项目数,不按
    n
    项目分组
  • 试试这个:

    var listOfStrings = new List<string>
    {
        "String 1",
        "String 2",
        "String 3",
        "String 4",
        "String 5",
        "String 6"
    };
    
    int step = 0;
    const int numTake = 3;
    for(var i = 0; i < listOfStrings.Count / numTake; i++)
    {
        Console.WriteLine("Starting a group!");
        foreach (var x in listOfStrings.Skip(3 * step++).Take(3))
        {
            Console.WriteLine(x);
        }
    }
    
    var listOfStrings=新列表
    {
    “字符串1”,
    “字符串2”,
    “字符串3”,
    “字符串4”,
    “字符串5”,
    “字符串6”
    };
    int步长=0;
    常量int numTake=3;
    对于(var i=0;i
    有很大的改进空间,但它应该让你知道如何完成这项任务

  • 在某些情况下,您需要这样做,但在开始使用LINQ时,您很可能不会遇到这些情况
  • 但当我运行此命令时,行仅包含例如“string1”和 这是一个角色一个角色的分裂

    这是因为
    Enumerable.Take
    将从
    IEnumerable
    中获取请求的项目数量。这使得
    x
    变量的类型为
    string
    ,您稍后将其调用为
    ToList()
    ,从而有效地创建了一个
    列表
    ,这不是您想要的

    您可以使用它的
    批处理
    扩展方法,它完全满足您的需要。它返回一个
    IEnumerable

    foreach(listofstring.batch(3)中的变量批)
    {
    //batch是一个IEnumerable,将有3项。
    foreach(批量中的var项目)
    {
    }
    }
    
    另一种可能性是自己创建扩展方法。这是取自:

    公共静态类EnumerableExtensions
    {
    公共静态IEnumerable批处理(此IEnumerable项,
    整数(最大项)
    {
    返回项。选择((项,inx)=>new{item,inx})
    .GroupBy(x=>x.inx/maxItems)
    .Select(g=>g.Select(x=>x.item));
    }
    }
    
    从您的代码开始:

    var listOfStrings = new List<string>
    {
        "String 1",
        "String 2",
        "String 3",
        "String 4",
        "String 5",
        "String 6"
    };
    
    foreach (var x in listOfStrings.Take(3).ToList())
    {
        var currRows = x.ToList();
    
        // currRows should have 3 items
        foreach (var itm in currRows)
        {
    
        }
    }
    
    var listOfStrings=新列表
    {
    “字符串1”,
    “字符串2”,
    “字符串3”,
    “字符串4”,
    “字符串5”,
    “字符串6”
    };
    foreach(listofstring.Take(3.ToList()中的变量x)
    {
    var currRows=x.ToList();
    //Currows应该有3项
    foreach(以当前行为单位的var itm)
    {
    }
    }
    
    让我们通过为正在循环的内容创建一个额外变量来简化代码:

    var listOfStrings = new List<string>
    {
        "String 1",
        "String 2",
        "String 3",
        "String 4",
        "String 5",
        "String 6"
    };
    
    var thingsYouAreLoopingOver = listOfStrings.Take(3).ToList();
    
    foreach (var x in thingsYouAreLoopingOver)
    {
        var currRows = x.ToList();
    
        // currRows should have 3 items
        foreach (var itm in currRows)
        {
    
        }
    }
    
    var listOfStrings=新列表
    {
    “字符串1”,
    “字符串2”,
    “字符串3”,
    “字符串4”,
    “字符串5”,
    “字符串6”
    };
    var thingsyouarelopingover=listofstring.Take(3.ToList();
    foreach(在thingsYouAreLoopingOver中的变量x)
    {
    var currRows=x.ToList();
    //Currows应该有3项
    foreach(以当前行为单位的var itm)
    {
    }
    }
    
    但这当然可以再次简化,因为您正在循环的内容只是listOfStrings的前三项内容,所以我们有:

    var thingsYouAreLoopingOver = new List<string>
    {
        "String 1",
        "String 2",
        "String 3"
    };
    
    foreach (var x in thingsYouAreLoopingOver)
    {
        var currRows = x.ToList();
    
        // currRows should have 3 items
        foreach (var itm in currRows)
        {
    
        }
    }
    
    var thingsyouarelopingover=新列表
    {
    “字符串1”,
    “字符串2”,
    “字符串3”
    };
    foreach(在thingsYouAreLoopingOver中的变量x)
    {
    var currRows=x.ToList();
    //Currows应该有3项
    foreach(以当前行为单位的var itm)
    {
    }
    }
    

    现在应该清楚你为什么会看到这种行为。

    这不是
    Take
    的工作原理。或者任何其他LINQ操作符,真的-他们从不修改原始集合。例如,您需要使用
    Take
    Skip
    的组合。将第二个循环替换为
    foreach(x中的var-itm)
    。不要对字符串调用
    ToList()
    ,因为它也是
    IEnumerable
    ,因此
    string.ToList()
    返回字符列表。其次,删除第一个循环中的
    ToList()
    调用,它什么也不做,而且浪费了CPU和内存。最后,
    Take(3)
    只取前3项,不按3分组。谢谢,MoreLinq确实非常方便。谢谢你解释为什么它没有像我预期的那样工作。
    var listOfStrings = new List<string>
    {
        "String 1",
        "String 2",
        "String 3",
        "String 4",
        "String 5",
        "String 6"
    };
    
    var thingsYouAreLoopingOver = listOfStrings.Take(3).ToList();
    
    foreach (var x in thingsYouAreLoopingOver)
    {
        var currRows = x.ToList();
    
        // currRows should have 3 items
        foreach (var itm in currRows)
        {
    
        }
    }
    
    var thingsYouAreLoopingOver = new List<string>
    {
        "String 1",
        "String 2",
        "String 3"
    };
    
    foreach (var x in thingsYouAreLoopingOver)
    {
        var currRows = x.ToList();
    
        // currRows should have 3 items
        foreach (var itm in currRows)
        {
    
        }
    }