Лучший способ удалить предметы из коллекции

Как лучше всего подойти к удалению элементов 9X_collections из коллекции на C#, если элемент известен, но 9X_c# не индексирован. Это один из способов сделать 9X_c# это, но в лучшем случае он кажется неэлегантным.

//Remove the existing role assignment for the user.
int cnt = 0;
int assToDelete = 0;
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
    if (spAssignment.Member.Name == shortName)
    {
        assToDelete = cnt;
    }
    cnt++;
}
workspace.RoleAssignments.Remove(assToDelete);

Что 9X_csharp мне действительно хотелось бы сделать, так 9X_collection это найти элемент, который нужно удалить, по 9X_c-sharp свойству (в данном случае по имени) без 9X_c# перебора всей коллекции и использования 9X_c-sharp двух дополнительных переменных.

79
2

  • Любите имена переменных. О ...
8
Общее количество ответов: 8

Ответ #1

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Если RoleAssignments - это List, вы можете использовать 9X_java-collections-api следующий код.

workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);

138
2

  • AFAIK, это удаление на месте.<p><span class ...

Ответ #2

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Если вы хотите получить доступ к членам 9X_visual-c# коллекции по одному из их свойств, вы можете 9X_.cs-file рассмотреть возможность использования вместо 9X_c#-language них Dictionary или KeyedCollection. Таким образом, вам не придется 9X_c#-language искать предмет, который вы ищете.

В противном 9X_c-sharp случае вы могли бы хотя бы так:

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
    if (spAssignment.Member.Name == shortName)
    {
        workspace.RoleAssignments.Remove(spAssignment);
        break;
    }
}

29
3

  • Это вызовет исключение, пото ...

Ответ #3

Ответ на вопрос: Лучший способ удалить предметы из коллекции

@smaclell спросил, почему обратная итерация 9X_collections более эффективна, в комментарии к @ sambo99.

Иногда это 9X_collections более эффективно. Предположим, у вас есть 9X_java-collections-api список людей, и вы хотите удалить или отфильтровать 9X_c#-language всех клиентов с кредитным рейтингом <1000;

У 9X_visual-c# нас есть следующие данные

"Bob" 999
"Mary" 999
"Ted" 1000

Если бы мы пошли 9X_csharp дальше, у нас вскоре были бы проблемы

for( int idx = 0; idx < list.Count ; idx++ )
{
    if( list[idx].Rating < 1000 )
    {
        list.RemoveAt(idx); // whoops!
    }
}

При 9X_c#.net idx = 0 мы удаляем Bob, который затем сдвигает 9X_collections все оставшиеся элементы влево. В следующий 9X_c#-language раз через цикл idx = 1, но list [1] теперь 9X_.cs-file Ted вместо Mary. В итоге мы по ошибке пропускаем 9X_.cs-file Mary. Мы могли бы использовать цикл while и 9X_.cs-file ввести больше переменных.

Или мы просто выполняем 9X_csharp обратную итерацию:

for (int idx = list.Count-1; idx >= 0; idx--)
{
    if (list[idx].Rating < 1000)
    {
        list.RemoveAt(idx);
    }
}

Все индексы слева от удаленного 9X_csharp элемента остаются прежними, поэтому вы не 9X_collections пропустите ни одного элемента.

Тот же принцип 9X_c#.net применяется, если вам дан список индексов, которые 9X_c#-language нужно удалить из массива. Чтобы не усложнять 9X_c-sharp задачу, вам нужно отсортировать список, а 9X_collection затем удалить элементы от самого высокого 9X_.cs-file индекса до самого низкого.

Теперь вы можете 9X_.cs-file просто использовать Linq и прямо заявлять 9X_c-sharp о своих действиях.

list.RemoveAll(o => o.Rating < 1000);

В этом случае удаление 9X_c-sharp одного элемента не более эффективно итерация 9X_c# вперед или назад. Вы также можете использовать 9X_c#.net для этого Linq.

int removeIndex = list.FindIndex(o => o.Name == "Ted");
if( removeIndex != -1 )
{
    list.RemoveAt(removeIndex);
}

23
1

  • Для простого List <t>, если вам нужно удалить более 1 элемента, обратный цикл for ВСЕГДА является наиболее эффективным способом сделать это. Это, безусловно, более эффективно, чем копирование данных в список listToRemove. Готов поспорить, реализаци ...

Ответ #4

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Если это ICollection, тогда у вас не будет метода RemoveAll. Вот 9X_csharp метод расширения, который сделает это:

    public static void RemoveAll(this ICollection source, 
                                    Func predicate)
    {
        if (source == null)
            throw new ArgumentNullException("source", "source is null.");

        if (predicate == null)
            throw new ArgumentNullException("predicate", "predicate is null.");

        source.Where(predicate).ToList().ForEach(e => source.Remove(e));
    }

На 9X_visual-c# основе: http://phejndorf.wordpress.com/2011/03/09/a-removeall-extension-for-the-collection-class/

12
0

Ответ #5

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Для простой структуры списка наиболее эффективным 9X_c# способом является использование реализации 9X_collection Predicate RemoveAll.

Например.

 workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);

Причины:

  1. Метод Predicate / Linq RemoveAll реализован в List и имеет доступ к внутреннему массиву, хранящему фактические данные. Он сдвинет данные и изменит размер внутреннего массива.
  2. Реализация метода RemoveAt довольно медленная и будет копировать весь базовый массив данных в новый массив. Это означает, что обратная итерация бесполезна для List

Если 9X_csharp вы застряли в реализации этого в эпоху до 9X_c#.net C# 3.0. У вас есть 2 варианта.

  • Легко обслуживаемый вариант. Скопируйте все совпадающие элементы в новый список и поменяйте местами базовый список.

Например.

List list2 = new List() ; 
foreach (int i in GetList())
{
    if (!(i % 2 == 0))
    {
        list2.Add(i);
    }
}
list2 = list2;

Или

  • Сложный, немного более быстрый вариант, который включает в себя смещение всех данных в списке вниз, когда они не совпадают, а затем изменение размера массива.

Если 9X_c#-language вы действительно часто удаляете данные из 9X_c#-language списка, возможно, лучше подойдет другая 9X_java-collections-api структура, например HashTable (.net 1.1), Dictionary (.net 9X_.cs-file 2.0) или HashSet (.net 3.5). для этого.

10
0

Ответ #6

Ответ на вопрос: Лучший способ удалить предметы из коллекции

К какому типу относится коллекция? Если 9X_c#-language это List, вы можете использовать полезный 9X_java-collections-api "RemoveAll":

int cnt = workspace.RoleAssignments
                      .RemoveAll(spa => spa.Member.Name == shortName)

(Это работает в .NET 2.0. Конечно, если 9X_.cs-file у вас нет более новой версии компилятора, вам 9X_java-collections-api придется вместо этого использовать "delegate 9X_c-sharp (SPRoleAssignment spa) {return spa.Member.Name 9X_visual-c# == shortName;}" красивого синтаксиса лямбда.)

Другой 9X_visual-c# подход, если это не список, но все же ICollection:

   var toRemove = workspace.RoleAssignments
                              .FirstOrDefault(spa => spa.Member.Name == shortName)
   if (toRemove != null) workspace.RoleAssignments.Remove(toRemove);

Для 9X_c#.net этого требуются методы расширения Enumerable. (Вы 9X_c#.net можете скопировать Mono, если вы застряли 9X_visual-c# на .NET 2.0). Если это какая-то настраиваемая 9X_c#-language коллекция, которая не может принимать элемент, но 9X_c# ДОЛЖНА принимать индекс, некоторые другие 9X_c-sharp методы Enumerable, такие как Select, передают 9X_csharp целочисленный индекс за вас.

7
0

Ответ #7

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Вот довольно хороший способ сделать это

http://support.microsoft.com/kb/555972

        System.Collections.ArrayList arr = new System.Collections.ArrayList();
        arr.Add("1");
        arr.Add("2");
        arr.Add("3");

        /*This throws an exception
        foreach (string s in arr)
        {
            arr.Remove(s);
        }
        */

        //where as this works correctly
        Console.WriteLine(arr.Count);
        foreach (string s in new System.Collections.ArrayList(arr)) 
        {
            arr.Remove(s);
        }
        Console.WriteLine(arr.Count);
        Console.ReadKey();

9X_java-collections-api

2
0

Ответ #8

Ответ на вопрос: Лучший способ удалить предметы из коллекции

Это мое общее решение

public static IEnumerable Remove(this IEnumerable items, Func match)
    {
        var list = items.ToList();
        for (int idx = 0; idx < list.Count(); idx++)
        {
            if (match(list[idx]))
            {
                list.RemoveAt(idx);
                idx--; // the list is 1 item shorter
            }
        }
        return list.AsEnumerable();
    }

Было бы намного проще, если 9X_collections бы методы расширения поддерживали передачу 9X_visual-c# по ссылке! использование:

var result = string[]{"mike", "john", "ali"}
result = result.Remove(x => x.Username == "mike").ToArray();
Assert.IsTrue(result.Length == 2);

РЕДАКТИРОВАТЬ: гарантирует, что 9X_c-sharp цикл списка остается действительным даже 9X_visual-c# при удалении элементов путем уменьшения 9X_c# индекса (idx).

2
0