컬렉션에서 항목을 제거하는 가장 좋은 방법

항목은 알고 있지만 색인은 모르는 경우 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);

제가 정말로 하고 싶은 것은 전체 컬렉션을 반복하고 두 개의 추가 변수를 사용하지 않고 속성(이 경우 이름)으로 제거할 항목을 찾는 것입니다.

질문에 대한 의견 (4)

역할 할당이 목록인 경우 다음 코드를 사용할 수 있습니다.

workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);
해설 (5)
해결책

컬렉션의 속성 중 하나로 컬렉션의 멤버에 액세스하려면 대신 사전 또는 키 컬렉션을 사용하는 것이 좋습니다. 이렇게 하면 찾고 있는 항목을 검색할 필요가 없습니다.

그렇지 않으면 최소한 이렇게 할 수 있습니다:

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

이유를 묻는 질문에 대한 논평을 @sambo99 보다 효율적인 역동기화 이터레이션에 @smaclell 있었다.

39 의 sometimes it& 더 효율적이다. You have a 고려해보십시오 목록니다 제거할 수 있는 사람, 또는 모든 고객에게 필터링합니다 신용등급 &lt. 1000년;

우리는 다음과 같은 데이터

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

만약 우리가 반복할 수 있으며, 곧 곤경에 빠지는 확보하십시오 we& 그렇고여 전달하십시오 # 39; d

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

'밥' 그러면 교대로 http://support. idx = 0 저희에게는힘과 분리하십시오 나머지 모든 요소를 떠나버렸소 하지만 다음에 루프를 통해 idx = 1 [1] 이제 '대신' 테드요 나열하십시오 마리아여 '. 왔냐는 마리아여 '를 통해 실수. 우리는 우리가 할 수 있으며, 더 많은 변수가 소개하십시오 while 루프는 사용할 수 있습니다.

또는, 우린 그냥 역동기화 반복.

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

왼쪽에 있는 그대로 유지될 수 있도록 모든 인덱스화합니다 재거됨 품목으로부터 don& t # 39, 모든 항목을 건너띄기.

39 의 경우, 이와 같은 원리를 qic you& indexe 제거하기 위해 어레이에서는 목록이 나온다. 셨으며 직선입니다 유지를 위해 필요한 항목 중 가장 높은 인덱스를 목록을 정렬하려면 그리곤요 분리하십시오 최저값.

이제 어떻게 하라고 # 39, Linq 선언하고 you& 간단한 방법으로 하게 됩니다.

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

이 경우 단일 항목을 제거하는 it& # 39 의 효율적인 앞으로 또는 뒤로 더 이상 반복. Linq 엔드입니다 사용할 수도 있습니다.

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

단순 List&lt T>; 가장 효율적인 방법은 구조를 사용하여 구축현 조건자 레모비올 것으로 보인다.

예.

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

그 이유는 다음과 같습니다.

  1. 이 방법은 조건자 / Linq 의 T&gt List&lt 레모비올 구현됩니까;; 내부 어레이입니다 액세스하려면 실제 데이터를 저장할 수 있다. 또 데이터 및 크기조정할 shift+ctrl 내부 어레이입니다.
  2. 이 방법은 매우 느리며 레모프스 구축현 복제할지 기본 어레이입니다 전체 데이터 를 새로운 어레이입니다. 즉, 역동기화 이터레이션에 List&lt 사용할 경우, T&gt.

이처럼 갇혀 있을 경우 벌이는 이 인할지 c # 3.0 은 이전 시대. 2) 옵션을 사용할 수 있습니다.

  • 이 옵션을 쉽게 관리할 수 있습니다. 그리고 기본 목록에 일치하는 항목을 모두 복제본에 스왑할 새 목록.

예.

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

또는

  • 이 옵션을 약간 빠르게 변화하고 있는 모든 데이터를 까다로운 部门从 다운되어도 않을 경우 다음 목록의 일치시킵니다 크기조정 이 어레이입니다.

아마도 그런거 정말 제거할 경우 수시로 바뀌엇어요 (.net 1.1) 같은 다른 구조를 해스터블 또는 사전 (.net 2.0) 또는 하시세 (.net 3.5) 가 이 더 적합할 것입니다.

해설 (0)

39 ',' s an it& 이콜레스티온 won& 그런 경우, 't have a # 39 레모비올' 메서드입니다. # 39 의 here& 확장명으로 할 수 있는 방법:

    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));
    }

기준: http://phejndorf.wordpress.com/2011/03/09/a-removeall-extension-for-the-collection-class/

해설 (1)

컬렉션의 유형은 무엇인가요? 목록 유형인 경우 유용한 '모두 제거'를 사용할 수 있습니다:

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

(이것은 .NET 2.0에서 작동합니다. 물론 최신 컴파일러가 없다면 멋진 람다 구문 대신 "delegate (SPRoleAssignment spa) { return spa.Member.Name == shortName; }" 를 사용해야 합니다.)

또 다른 접근 방식은 목록이 아니지만 여전히 ICollection인 경우입니다:

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

이를 위해서는 Enumerable 확장 메서드가 필요합니다. (.NET 2.0을 사용하는 경우 Mono 메서드를 복사할 수 있습니다). 항목을 가져올 수 없지만 인덱스를 가져와야 하는 사용자 정의 컬렉션인 경우 Select와 같은 다른 Enumerable 메서드 중 일부가 정수 인덱스를 대신 전달합니다.

해설 (0)

이것은 상당히 좋은 길일

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();
해설 (0)

이건 내 일반 솔루션

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();
    }

이 경우 훨씬 더 단순한 확장명은 메서드을 지원부에서는 엿볼 반군지역 참조별로! 사용법:

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

편집: 목록에 항목을 삭제하는 경우에도 남아 있는 보장 루프을 유효함 데크레멘팅 인덱스 (idx).

해설 (4)

Linq 할 수 있는 최선의 방법을 사용하는 것입니다.

예 클래스:

 public class Product
    {
        public string Name { get; set; }
        public string Price { get; set; }      
    }

Linq 쿼리하지:

var subCollection = collection1.RemoveAll(w => collection2.Any(q => q.Name == w.Name));

이 쿼리는 요소를 모두 분리하십시오 collection1 "이름" "만약 '요소' 이름 '에서' collection2 일치하는

사용해야 합니다. ',' 시스템드링크 사용하여

해설 (0)

이를 통해 얻을 수 없는 동안 루프을 수집 및 수정, 이는 과거 조롱했기 외곽진입 I& idfsysobject. 취합은 # 39, ve (참고합니다 네스토리스트 () at the end of the original collection, 이로 인해 다른 취합은 메모리에 관심용 기존 취합은 수정할 수 있습니다)

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments.ToList())
{
    if (spAssignment.Member.Name == shortName)
    {
        workspace.RoleAssignments.Remove(spAssignment);
    }
}
해설 (0)

39 you& 좁히어 가 다른 외곽진입 취할 수 있는 방법에 따라 사용, re 뜻한다. # 39, re 다운로드하십시오 you& 경우 지정 1 회 (예를 들어, 이 때 앱 실행) 에 있는 컬렉션 즉석에서 해스터블 변환하기에 수 있습니다.

쇼트나미 = &gt. 스파롤라시니망

이렇게 하면 제거할 때 보라그들은 각 항목을 파선-짧은 이름, all you need to do 는 해스터블 항목 분리하십시오 에서 주요 산업별로.

39, 이 경우, re 로드중 죄송합니다. you& 스파롤라시니멘츠 많이유 isn& 될 것은 더 이상 비용 효율성 측면에서, t # 39 시간입니다. 다른 사람이 만든 경우, Linq 약간만이라도 优秀 you& 사용에 대한 제안을 하고 있지만, 그렇지 않으면 # 39 의 새 버전을 사용하는 .NET Framework you& # 39, ll %s/dbase/ext_table. you& # 39, re 고수할 방법을 사용하여.

해설 (0)

사전 취합은 관점, 유사한 해봤다고.

Dictionary sourceDict = new Dictionary();
sourceDict.Add("Sai", true);
sourceDict.Add("Sri", false);
sourceDict.Add("SaiSri", true);
sourceDict.Add("SaiSriMahi", true);

var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false);

foreach (var item in itemsToDelete)
{
    sourceDict.Remove(item.Key);
}
  • Note:* Net 의 코드 위에 페일오버됩니다 클라이언트별로 프로파일할 (3.5-4.5) 도 일부 시청자들이 언급한 것은 그들을 위한 .Net4.0 못하고 있는 설정이면 문제가 아니라 확실하지 않다.

그래서 대체하십시오 코드 (네스토리스트 ()) 의 아래에 있는, 그런 상황을 피하기 위한 기술서임을 오류:. "취합은 수정되었습니다. 열거도 작업이 실행되지 않을 수 있습니다. "

var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false).ToList();

Msdn 에서 호스트당 .Net4.5 이후 클라이언트입니다 프로파일할 단종됩니다. 이아스파스 http://msdn.microsoft.com/en-us/library/cc656912 (v = vs. 110)

해설 (0)

먼저 먹이좀 항목을 삭제하는 것보다.

var itemsToDelete = Items.Where(x => !!!your condition!!!).ToArray();
for (int i = 0; i < itemsToDelete.Length; ++i)
    Items.Remove(itemsToDelete[i]);

해당 품목을 클래스용 무시하려면 게타시코드 () '가' 합니다.

해설 (0)

여기서 많은 좋은 반응을. 내가 특히 좋아하는 람다 엑스프레시론스버리 청소하십시오. 그러나 그는 specifying 않는 태만 한 종류를 뜻한다. 이는 스파롤라시니망콜레스티온 대뿐입니다 제거 (int) 및 제거 (스프린시펄) () 의 모스요) 가 아닌 휴대용 레모비올 (). 그래서, 나는 이에 대해 더 나은 모습으로 없으면 제안이다.

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
                        {
                            if (spAssignment.Member.Name != shortName) continue;
                            workspace.RoleAssignments.Remove((SPPrincipal)spAssignment.Member);
                            break;
                        }
해설 (1)