2016-03-23 2 views
2

У меня есть список объектов, которые я хочу удалить каждый элемент в свою очередь, который изменяет длину списка по мере его поступления, Работа. Это трудно объяснить, так что я буду просто показать код:Каков наилучший способ перебора списка, если вы уничтожаете его содержимое по мере того, как вы идете

public List<GameObject> ActiveChunks = new List<GameObject>(); 

public static void DeActivate(GameObject Obj) 
{ 
    //Do lots of other stuff based on the Obj 
    .... 
    .... 
    instance.ActiveChunks.Remove(Obj); 
} 

public static void DeActivateAllChunks() 
{ 
    for (int c = 0; c < instance.ActiveChunks.Count; c++) 
    { 
     DeActivate(instance.ActiveChunks[c], false); 
    } 
} 

Как вы можете видеть, что цикл проходит через мой список активного кусковых вызывающий функцию деактивировать, которая делает некоторые вещи на объекте, а затем удаляет элемента из списка. Мой вопрос в том, есть ли лучший способ перебора через список, который изменяется?

+2

Вам нужно сделать копию списка и удалить элементы из копии –

+2

итерации от графа до 0 с '--'? – Marnix

+0

Я думаю, что вы получите ошибки, удаляющиеся из списка, когда вы перебираете его вперед. Вам нужно вернуться назад 'for (var c = instance.ActiveChunks.Count - 1; c> = 0; c -)' –

ответ

1

Вариант 1) Вы можете сохранить список в новой переменной и закодировать исходный список, а затем удалить элементы в переменной temp. Наконец, используйте временную переменную.

public List<GameObject> ActiveChunks = new List<GameObject>(); 
var tempActiveChunks = ActiveChunks; //temp variable 

public static void DeActivate(GameObject Obj) 
{ 
    //Do lots of other stuff based on the Obj 
    .... 
    .... 
    tempActiveChunks.Remove(Obj); 
} 

public static void DeActivateAllChunks() 
{ 
    for (int c = 0; c < instance.ActiveChunks.Count; c++) 
    { 
     DeActivate(instance.ActiveChunks[c], false); 
    } 
    instance.ActiveChunks = tempActiveChunks; 
} 

Вариант 2) Также вы можете перемещаться от задом наперед, как показано ниже

public static void DeActivateAllChunks() 
{ 
    for (int c = instance.ActiveChunks.Count - 1; c >=0 ; c--) 
    { 
     DeActivate(instance.ActiveChunks[c], false); 
    } 
} 

Вариант 3 Благодаря Sac, Вы можете скопировать список в переменную темп а затем перебираем переменную temp и удаляем элемент из фактического списка.

public List<GameObject> ActiveChunks = new List<GameObject>(); 
    var tempActiveChunks = ActiveChunks; //temp variable 

    public static void DeActivate(GameObject Obj) 
    { 
     //Do lots of other stuff based on the Obj 
     .... 
     .... 
     instance.ActiveChunks.Remove(Obj); 
    } 

    public static void DeActivateAllChunks() 
    { 
     for (int c = 0; c < tempActiveChunks.Count; c++) 
     { 
      DeActivate(instance.ActiveChunks[c], false); 
     }    
    } 
+1

Если бы я был вами, тогда я буду копировать «ActiveChunks» и перебирать этот скопированный список при удалении из «ActiveChunks». – Sachin

+0

@Sac Добавлено ваше предложение тоже в ответ спасибо, Да, это кажется правильным, но из интереса есть ли проблема с производительностью с 1-м вариантом? –

+0

Спасибо всем, все хорошие предложения. Это используется в обновлении фрейма в игре, поэтому я пойду с переходом назад по списку, поскольку я не уверен в стоимости выполнения копирования копии списка. – user2163342

0

Вы можете пройти через них в обратном направлении:

public static void DeActivateAllChunks() 
{ 
    for (int c = instance.ActiveChunks.Count - 1; c >=0 ; c--) 
    { 
     DeActivate(instance.ActiveChunks[c], false); 
    } 
} 
0

Измените для контура, чтобы сосчитать назад, а не вперед. Таким образом удаление/уничтожение не влияет на следующую строку, которую вы собираетесь получить.

for (int c = instance.ActiveChunks.Count - 1; c >= 0; c--) 
{ 
    DeActivate(instance.ActiveChunks[c], false); 
} 
0

Вам не нужна петля и дополнительная индексная переменная. Следующий подход лучше:

while(ActiveChunks.Count > 0) { 
    var theLastIndex = ActiveChunks.Count - 1; 
    var temp = ActiveChunks[theLastIndex]; 
    ActiveChunks.RemoveAt(theLastIndex); 
    // deactivate object removed from the list 
    DeActivate(temp); 
} 
0

Я думаю, что это гибкий способ, попробовать этот

public static List<GameObject> ActiveChunks = new List<GameObject>(); 

     public static bool DeActivate(GameObject Obj) 
     { 
      if(true)//your condition 
      { 
       return true;//do not remove the object 
      } 
      else 
      { 
       return false;//remove the object 
      } 
     } 

     public static void DeActivateAllChunks() 
     { 
      ActiveChunks = ActiveChunks.Where(c => DeActivate(c)).ToList(); 
     } 
Смежные вопросы