2016-04-16 1 views
1

Я хочу удалить элемент из списка в зависимости от состояния. Проблема в том, что я не могу удалить ее, итерации ее вперед, так как ее массив, например, реализация, и это изменяет структуру и количество списков.C# Удаление элемента при перемещении списка-повторение назад или использование i- или использование linq для повторного и одновременного удаления?

Так я прочитал это в ответ я был убежден, что это должно быть решение: how-to-remove-elements-from-a-generic-list-while-iterating-over-it

Но кто-то дал мне обратную связь, что это не так легко понять, поскольку мы переборе в обратном направлении, а мы должны перебирать вперед и делать i - всякий раз, когда выполняется условие удаления.

var list = new List<int>(Enumerable.Range(1, 10)); 
for (int i = 0; i < list.Count; i++) 
{ 
    if (list[i] > 5) 
    { 
     list.RemoveAt(i); 
     i--; 
    } 
} 
list.ForEach(i => Console.WriteLine(i)); 

I протестированы этот подход и результаты, как и ожидалось, но я по-прежнему опасаются, что это будет одинаковым для всех возможных случаев, так как я не получил этот ответ нигде в каком-нибудь форуме, и все было предложено перебирать в обратном направлении.

Может ли кто-нибудь сказать, будут ли оба решения вести себя одинаково или они отличаются?

+0

Почему бы вам не нравится [ 'Список .RemoveAll'] (https://msdn.microsoft.com/en-us/library/wdka673a.aspx)? –

ответ

2

Предпочтительный способ удаления элементов из списка, в месте, чтобы сделать это в обратном направлении, с такой код:

int index = list.Count - 1; 
while (index >= 0) 
{ 
    if (expression identifying item to remove) 
     list.RemoveAt(index); 
    else 
     index--; 
} 

Теперь, имейте в виду, что это относится только к удалению в список на месте, что означает, что вы не хотите создавать новый список элементов для хранения. Если вы можете это сделать, создайте новый список с сохраненными элементами, возможно, выражение LINQ лучше.

Таким образом, Почему является вышеуказанным подходом?

Хорошо, рассмотрите это. Что означает «удаление элемента из списка»? Основная структура данных List<T> в C# представляет собой массив. Удаление элемента из массива действительно невозможно, но вы можете перемещать значения внутри массива. Чтобы «удалить» элемент из массива, вы можете переместить все элементы, следующие за ним, на один индекс вверх.

Это операция, которая займет время относительно количества предметов, следующих за ней.

Итак, давайте посмотрим на это в «прямом приближении». В этом подходе вы начинаете с индекса 0 и каждый раз, когда вы находите элемент, сохраняетесь, но вы также удаляете элемент, перемещая каждый элемент, следующий за ним, на один элемент вниз.

Давайте сделаем простой пример: у вас есть список из каждого числа от 1 до 10, и вы хотите удалить все четные значения элемента (2, 4, 6, 8 и т. Д.).

Так у вас есть это:

1 2 3 4 5 6 7 8 9 10 

Первый пункт, чтобы удалить это 2, это будет двигаться каждый номер, который следует за ним, 3 до 10, один индекс вниз.Это 8 номеров.

Следующий элемент: 4, он должен будет перемещаться с 5 по 10 вниз, что составляет 6 номеров. Теперь мы переместили 14 номеров.

Далее - 6, перемещение с 7 на 10 вниз, то есть 4 числа, теперь мы перемещаем до 18 номеров.

Далее 8, перемещение 9 и 10, 2 цифры, Мы переместились до 20 номеров.

Поскольку числа не соответствуют последним, которые мы хотим удалить, 10, мы переместили всего 20 чисел.

Теперь давайте сделаем это в обратном порядке.

Сначала мы посмотрим на 10, мы хотим удалить это, никакие цифры не следуют за ним, поэтому никаких перемещений.

Далее мы хотим удалить 8, за ним следует только одно число, поэтому мы перемещаем 9 вниз на одну ступень. 10 уже был удален, поэтому он больше не присутствует.

Дальше мы хотим удалить 6. После него следуют два номера, 7 и 9, поэтому сдвиньте их вниз, всего 3 числа.

Удалить 4, после этого 5, 7 и 9, так что теперь мы переместили всего 6 чисел.

Удалить 2 - 3, 5, 7 и 9 следует за ним теперь мы переместили всего 10 номеров.

Так что, имея дело со списком, оно полностью зависит от того, что вы имеете в виду «ведет себя одинаково».

Будет ли конечный результат одинаковым, если мы рассмотрим только те номера, которые остались в конечном списке?

Да.

Будет ли общая продолжительность работы одинаковой?

No.

0

Я бы предложил не просто использовать индекс, чтобы удалить элементы из списка на итерации. Простое использование Linq Select с условием. Это приведет к тому, что вы получите новый список.

var list = new List<int>(Enumerable.Range(1, 10)); 
var newList= list.Select(number=>number<=5).ToList(); 

И теперь новый список будет содержать только те элементы, которые удовлетворяют условию, которое вы предоставляете в выражении лямбда.

+0

, но он не удалял выбранные элементы из исходного списка. Мне нужно удалить их и использовать список с вычитаемыми элементами в другом месте. – maverick

+0

В порядке, если я правильно понимаю вашу проблему, вы собираетесь использовать список после удаления некоторых элементов на основе некоторого состояния. Так что мой код выше. Он не удалит ничего из исходного списка. он просто создаст для вас новый список после фильтрации элементов из исходных результатов, используя ваше условие. вы можете использовать новый список где-то еще. –