항목은 알고 있지만 색인은 모르는 경우 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);
제가 정말로 하고 싶은 것은 전체 컬렉션을 반복하고 두 개의 추가 변수를 사용하지 않고 속성(이 경우 이름)으로 제거할 항목을 찾는 것입니다.
컬렉션의 속성 중 하나로 컬렉션의 멤버에 액세스하려면 대신 사전
또는 키 컬렉션
을 사용하는 것이 좋습니다. 이렇게 하면 찾고 있는 항목을 검색할 필요가 없습니다.
그렇지 않으면 최소한 이렇게 할 수 있습니다:
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
if (spAssignment.Member.Name == shortName)
{
workspace.RoleAssignments.Remove(spAssignment);
break;
}
}
이유를 묻는 질문에 대한 논평을 @sambo99 보다 효율적인 역동기화 이터레이션에 @smaclell 있었다.
우리는 다음과 같은 데이터
"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, 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);
}
단순 List< T>; 가장 효율적인 방법은 구조를 사용하여 구축현 조건자 레모비올 것으로 보인다.
예.
workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);
그 이유는 다음과 같습니다.
이처럼 갇혀 있을 경우 벌이는 이 인할지 c # 3.0 은 이전 시대. 2) 옵션을 사용할 수 있습니다.
예.
List<int> list2 = new List<int>() ;
foreach (int i in GetList())
{
if (!(i % 2 == 0))
{
list2.Add(i);
}
}
list2 = list2;
또는
아마도 그런거 정말 제거할 경우 수시로 바뀌엇어요 (.net 1.1) 같은 다른 구조를 해스터블 또는 사전 (.net 2.0) 또는 하시세 (.net 3.5) 가 이 더 적합할 것입니다.
public static void RemoveAll<T>(this ICollection<T> source,
Func<T, bool> 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/
컬렉션의 유형은 무엇인가요? 목록 유형인 경우 유용한 '모두 제거'를 사용할 수 있습니다:
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 메서드 중 일부가 정수 인덱스를 대신 전달합니다.
이것은 상당히 좋은 길일
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();
이건 내 일반 솔루션
public static IEnumerable<T> Remove<T>(this IEnumerable<T> items, Func<T, bool> 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).
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 일치하는
사용해야 합니다. ',' 시스템드링크 사용하여
이를 통해 얻을 수 없는 동안 루프을 수집 및 수정, 이는 과거 조롱했기 외곽진입 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);
}
}
쇼트나미 = >. 스파롤라시니망
이렇게 하면 제거할 때 보라그들은 각 항목을 파선-짧은 이름, all you need to do 는 해스터블 항목 분리하십시오 에서 주요 산업별로.
사전 취합은 관점, 유사한 해봤다고.
Dictionary<string, bool> sourceDict = new Dictionary<string, bool>();
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);
}
그래서 대체하십시오 코드 (네스토리스트 ()) 의 아래에 있는, 그런 상황을 피하기 위한 기술서임을 오류:. "취합은 수정되었습니다. 열거도 작업이 실행되지 않을 수 있습니다. "
var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false).ToList();
Msdn 에서 호스트당 .Net4.5 이후 클라이언트입니다 프로파일할 단종됩니다. 이아스파스 http://msdn.microsoft.com/en-us/library/cc656912 (v = vs. 110)
여기서 많은 좋은 반응을. 내가 특히 좋아하는 람다 엑스프레시론스버리 청소하십시오. 그러나 그는 specifying 않는 태만 한 종류를 뜻한다. 이는 스파롤라시니망콜레스티온 대뿐입니다 제거 (int) 및 제거 (스프린시펄) () 의 모스요) 가 아닌 휴대용 레모비올 (). 그래서, 나는 이에 대해 더 나은 모습으로 없으면 제안이다.
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
if (spAssignment.Member.Name != shortName) continue;
workspace.RoleAssignments.Remove((SPPrincipal)spAssignment.Member);
break;
}