Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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# for循环中的更改列表_C#_List_For Loop - Fatal编程技术网

C# for循环中的更改列表

C# for循环中的更改列表,c#,list,for-loop,C#,List,For Loop,我正在尝试修改for值中的列表 for (int i = 0; i < theList.Count; i++) { if(someCircunstances) theList.remove(component); else theList.add(component); } for(int i=0;iArgumentOutOfRangeException 所以为了解决这个问题,我建议您将其拆分为两个for循环: for (int i = t

我正在尝试修改for值中的列表

for (int i = 0; i < theList.Count; i++) {
    if(someCircunstances)
        theList.remove(component);
    else
        theList.add(component);
}
for(int i=0;i
使用此方法,我得到一个
ArgumentOutOfRangeException

有什么方法可以做到这一点吗?

在迭代列表时对列表进行变异也是一种不好的做法

这是另一种选择:

theList.RemoveAll(someCircunstances);

可以通过向后迭代并使用索引而不是项来解决此问题:

for (int i = list.Count - 1; i > 0; i--)
{
    if(condition)
        list.RemoveAt(i);
    else
        list.Add(component);
}
一些解释:当您迭代集合时,不应该更改范围中的项。迭代器将检测到并抛出(在
foreach
的情况下,您必须使用列表的副本)。但是如果使用索引(
RemoveAt()
method),并且在向后迭代时,对于下一次迭代,您是安全的,范围不包括已删除的项<代码>添加()
正在添加到末尾,因此新项永远不在范围内


我将再添加几个解决方案,您自己决定哪一个更好:

先复制的经典foreach:

foreach(var item in list.ToArray()) // imho `ToArray` is better than `ToList`
    if(condition)
        list.Remove(item);
    else
        list.Add(component);
新名单如下:

var result = new List<...>();
foreach(var item in list)
    result.Add(condition ? component : item); // not sure here, but should give you idea
list = result;
var result=newlist();
foreach(列表中的变量项)
结果.添加(条件?组件:项);//这里不确定,但应该给你一个主意
列表=结果;

由于索引从0开始,您将获得一个超出范围的异常

如上所述,一种解决方案是从list.count中删除1,另一种解决方案是在1而不是0处启动i

试想一下:如果列表中有1个元素,那么该元素的索引为0;如果有100个元素,那么第100个元素的索引为99


您认为列表像:[1][2][3],而实际上它是[0][1][2]

这里的问题是,您正在从列表中删除值,然后使用已删除的索引再次遍历它->
ArgumentOutOfRangeException

所以为了解决这个问题,我建议您将其拆分为两个for循环:

for (int i = theList.Count - 1; i >= 0; i--) {
    if(someCircunstances)
        theList.remove(component);
}

for (int i = 0; i < theList.Count; i++) {
    if(someCircunstances)
        theList.add(component);
}
for(int i=list.Count-1;i>=0;i--){
if(某些循环)
列表。移除(组件);
}
对于(int i=0;i
我同意塔马斯的观点,即在迭代时不要改变列表,还有另一种方法可以达到你的目的

 List<someType> ToRemove=new List<someType>() ; //some type is same type as theList is  
 List<someType> ToAdd=new List<someType>();

for (int i = 0; i < theList.Count; i++) {
 if(someCircunstances)
     ToRemove.add(component);
 else
     ToAdd.add(component);
}

 theList=((theList.Except(ToRemove)).Concat(ToAdd)).ToList();
List-ToRemove=新列表()//某些类型与列表的类型相同
List ToAdd=新列表();
对于(int i=0;i
根据注释,您需要能够为新创建的项目应用相同的逻辑

您需要这样做:

public void DoIt(List<MyObject> theList)
{
    List<MyObject> items_to_remove = new List<MyObject>();

    List<MyObject> items_to_add = new List<MyObject>();

    for (int i = 0; i < theList.Count; i++)
    {
        if (someCircunstances)
            items_to_remove.Add(....); //Remove some existing item
        else
            items_to_add.Add(....); //Add a new item
    }

    if(items_to_remove.Count > 0)
        items_to_remove.ForEach(x => theList.Remove(x));

    if (items_to_add.Count > 0)
    {
        DoIt(items_to_add); //Recursively process new objects 

        theList.AddRange(items_to_add);
    }
}
public void DoIt(列表)
{
List items_to_remove=新建列表();
列表项_to_add=新列表();
对于(int i=0;i0)
items_to_remove.ForEach(x=>list.remove(x));
如果(项添加到项计数>0)
{
DoIt(items_to_add);//递归地处理新对象
列表添加范围(项添加到项添加);
}
}
其思想是将要添加的项和要删除的项插入到它们自己的列表中

然后在迭代之后,删除需要删除的项

之后,您需要添加要添加的项目。但是,在这样做之前,您需要对它们运行相同的逻辑,这就是递归调用的解释


请注意,我使用的是
MyObject
,因为我不知道您列表的类型。使用您正在使用的任何类型。

如果您可以使用循环的当前索引从lst中删除项目,您可以像这样轻松地执行此操作:

using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            var numbers = Enumerable.Range(1, 20).ToList();
            var rng = new Random();

            for (int i = 0; i < numbers.Count; ++i)
            {
                if (rng.NextDouble() >= 0.5) // If "someCircumstances"
                {
                    numbers.Add(numbers[i]*2);
                }
                else
                {
                    // Assume here you have some way to determine the 
                    // index of the item to remove. 
                    // For demo purposes, I'll just calculate a random index.

                    int index = rng.Next(0, numbers.Count);

                    if (index >= i)
                        --i;

                    numbers.RemoveAt(index);
                }
            }

            Console.WriteLine(string.Join("\n", numbers));
        }
    }
}
使用系统;
使用System.Linq;
命名空间控制台应用程序1
{
班级计划
{
静态void Main()
{
var numbers=Enumerable.Range(1,20).ToList();
var rng=新随机数();
对于(int i=0;i=0.5)//if“某些情况”
{
编号。添加(编号[i]*2);
}
其他的
{
//假设你有办法确定
//要删除的项的索引。
//出于演示目的,我将只计算一个随机索引。
int index=rng.Next(0,number.Count);
如果(索引>=i)
--一,;
数字。删除(索引);
}
}
Console.WriteLine(string.Join(“\n”,数字));
}
}
}
这也将遍历添加到列表末尾的所有数字。
numbers.Count的值在每次迭代时都会重新计算,因此当它发生变化时,循环将被适当地扩展


(主题外)额外问题:在上面的代码中,当循环退出时,列表的平均大小是多少?最大尺寸是多少?

可能您没有正确的
组件的引用。你是怎么理解这个引用的?我知道,当第五个iterarion出现时它崩溃了,我调试了一个实例,发现崩溃与删除和添加函数无关。你需要将for循环从Count-1反转为0,你的意思是
for(int I=theList.Count-1;I<0;I++)
在迭代过程中添加的项目如何?你想对它们进行迭代吗?我需要从列表中删除“坏”节点,我无法将其全部删除。塔马斯是对的,只需编写类似列表的内容。RemoveAll(item=>SomeCircunStatesMatch(item));如果你想这么做,我