LINQ를 사용하여 목록이 비어 있는지 확인하는 중
목록이 비어 있는지 여부를 확인하는 "최고의" 방법은 무엇입니까(속도와 가독성을 모두 고려한 것)?목록이 유형인 경우에도IEnumerable<T>그리고 Count 속성이 없습니다.
지금 나는 이것들 사이에서 엎치락뒤치락하고 있습니다.
if (myList.Count() == 0) { ... }
그리고 이것은:
if (!myList.Any()) { ... }
두 번째 옵션은 첫 번째 항목을 보는 즉시 결과를 제공하기 때문에 두 번째 옵션이 더 빠르지만, 두 번째 옵션(IE 숫자의 경우)은 모든 항목을 방문하여 카운트를 반환해야 합니다.
그렇긴 하지만, 두 번째 옵션이 당신이 읽을 수 있을 것 같습니까?당신은 어떤게 좋아요?아니면 빈 목록을 테스트할 수 있는 더 나은 방법을 생각해 낼 수 있습니까?
Edit @lassevk의 응답이 가장 논리적인 것으로 보이며, 가능하면 캐시된 수를 사용하기 위한 약간의 런타임 검사와 함께 다음과 같습니다.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list is ICollection<T>) return ((ICollection<T>)list).Count == 0;
return !list.Any();
}
다음과 같이 할 수 있습니다.
public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
return true; // or throw an exception
return !source.Any();
}
편집: 를 사용하면 됩니다.기본 소스가 실제로 fastCount 속성을 가지고 있는 경우 Count 메서드가 빠릅니다.위의 유효한 최적화는 몇 가지 기본 유형을 감지하고 를 사용하는 것입니다.대신 이러한 속성을 카운트합니다.임의() 접근 방식이지만 보장할 수 없는 경우 다시 .Any()로 이동합니다.
한 것처럼 한 가지 하겠습니다: : 또확하십인한습겠추신하가나항.ICollection에 의해서도 구현되기 때문에 (즉, ▁as때▁(,Queue<T>그리고.Stack<T>) 또한 사용할 것입니다.as에 is더 관용적이고 더 빠른 것으로 나타났기 때문입니다.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == 0;
}
var nonGenericCollection = list as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == 0;
}
return !list.Any();
}
LINQ 자체는 Count() 방법을 중심으로 심각한 최적화를 수행하고 있어야 합니다.
이것이 당신을 놀라게 합니까?나는 그것을 상상합니다.IList »,Count 의 수를 동안에 요소의 수를 읽습니다.Any.IEnumerable.GetEnumerator하고 호출합니다.MoveNext한 번쯤은
/EDIT @Matt:
IEnumberable에 대한 Count() 확장 방법이 다음과 같은 작업을 수행하고 있다고 가정할 수 있습니다.
네, 물론 그렇습니다.이런 뜻이었어요.사실, 그것은 사용합니다.ICollection에 IList하지만 결과는 같습니다.
방금 간단한 테스트를 작성했습니다. 이것을 사용해 보십시오.
IEnumerable<Object> myList = new List<Object>();
Stopwatch watch = new Stopwatch();
int x;
watch.Start();
for (var i = 0; i <= 1000000; i++)
{
if (myList.Count() == 0) x = i;
}
watch.Stop();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (var i = 0; i <= 1000000; i++)
{
if (!myList.Any()) x = i;
}
watch2.Stop();
Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
Console.ReadLine();
두 번째는 거의 세 배 느립니다 :)
스택 또는 어레이 또는 기타 시나리오를 사용하여 스톱워치 테스트를 다시 시도하는 것은 실제로 보이는 목록의 유형에 따라 달라집니다. 이는 카운트가 더 느리다는 것을 증명하기 때문입니다.
따라서 사용하는 목록의 유형에 따라 다를 수 있습니다!
(참고로, 저는 목록에 2000개 이상의 객체를 넣었고 다른 유형과 반대로 여전히 더 빨랐습니다.)
List.Count마이크로소프트 문서에 따르면 is O(1):
http://msdn..com/en-us/library/27b47ht3.aspxhttp ://msdn.microsoft.com/en-us/library/27b47ht3.aspx
그러니 그냥 사용하세요.List.Count == 0
이는 목록에서 무언가가 추가되거나 제거될 때마다 업데이트되는 카운트라는 데이터 구성원이 있기 때문입니다.List.Count데이터를 얻기 위해 모든 요소를 반복할 필요는 없습니다. 데이터 구성원만 반환합니다.
항목이 여러 개인 경우 두 번째 옵션이 훨씬 빠릅니다.
Any()항목이 하나 발견되는 즉시 반환됩니다.Count()계속해서 전체 목록을 살펴봐야 합니다.
예를 들어 열거형에 1000개의 항목이 있다고 가정합니다.
Any()첫 번째를 확인한 다음 true를 반환합니다.Count()전체 열거형을 통과한 후 1000을 반환합니다.
이것은 술어 재정의 중 하나를 사용하는 경우 더 심각해질 수 있습니다. Count()는 여전히 모든 항목을 확인해야 합니다. 일치 항목이 하나만 있더라도 마찬가지입니다.
Any 하나를 사용하는 것에 익숙해질 것입니다. 이것은 의미가 있고 읽기 쉽습니다.
한 가지 주의할 점 - IE 번호가 아닌 목록이 있는 경우 해당 목록의 개수 속성을 사용합니다.
@콘라드를 놀라게 한 것은 제 테스트에서, 저는 목록을 수용하는 방법으로 전달하고 있다는 것입니다.IEnumerable<T>은 "()"에 대한 Count수 .IList<T>.
IEnumberable에 대한 Count() 확장 방법이 다음과 같은 작업을 수행하고 있다고 가정할 수 있습니다.
public static int Count<T>(this IEnumerable<T> list)
{
if (list is IList<T>) return ((IList<T>)list).Count;
int i = 0;
foreach (var t in list) i++;
return i;
}
말해,한 경우에 최적화입니다.IList<T>.
/mate - /EDIT @Konrad +1에 가능성이 더 ICollection<T>.
좋아요, 그럼 이건 어때요?
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable.GetEnumerator().MoveNext();
}
편집: 누군가가 이미 이 솔루션을 스케치했다는 것을 방금 깨달았습니다.Any() 메서드가 이 작업을 수행할 것이라고 언급했지만 직접 수행하지 않는 이유는 무엇입니까?안부 전해요
다른 아이디어:
if(enumerable.FirstOrDefault() != null)
하지만 저는 Any() 접근 방식이 더 좋습니다.
이 작업을 Entity Framework와 함께 수행하기 위해서는 매우 중요했습니다.
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
//your code
}
Count()에 확인하면 Linq가 데이터베이스에서 "SELECT COUNT(*)"를 실행하지만 결과에 데이터가 포함되어 있는지 확인해야 하므로 Count() 대신 FirstOrDefault()를 도입하기로 결정했습니다.
전에
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
if (cfop.Count() > 0)
{
var itemCfop = cfop.First();
//....
}
끝나고
var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()
var itemCfop = cfop.FirstOrDefault();
if (itemCfop != null)
{
//....
}
private bool NullTest<T>(T[] list, string attribute)
{
bool status = false;
if (list != null)
{
int flag = 0;
var property = GetProperty(list.FirstOrDefault(), attribute);
foreach (T obj in list)
{
if (property.GetValue(obj, null) == null)
flag++;
}
status = flag == 0 ? true : false;
}
return status;
}
public PropertyInfo GetProperty<T>(T obj, string str)
{
Expression<Func<T, string, PropertyInfo>> GetProperty = (TypeObj, Column) => TypeObj.GetType().GetProperty(TypeObj
.GetType().GetProperties().ToList()
.Find(property => property.Name
.ToLower() == Column
.ToLower()).Name.ToString());
return GetProperty.Compile()(obj, str);
}
단 타오의 대답을 술어로 설명하자면 다음과 같습니다.
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any(predicate);
}
public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw new ArgumentNullException();
if (IsCollectionAndEmpty(source)) return true;
return !source.Any();
}
private static bool IsCollectionAndEmpty<TSource>(IEnumerable<TSource> source)
{
var genericCollection = source as ICollection<TSource>;
if (genericCollection != null) return genericCollection.Count == 0;
var nonGenericCollection = source as ICollection;
if (nonGenericCollection != null) return nonGenericCollection.Count == 0;
return false;
}
List<T> li = new List<T>();
(li.First().DefaultValue.HasValue) ? string.Format("{0:yyyy/MM/dd}", sender.First().DefaultValue.Value) : string.Empty;
myList.ToList().Count == 0이상입니다
이 확장 방법은 다음과 같습니다.
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
try
{
enumerable.First();
return false;
}
catch (InvalidOperationException)
{
return true;
}
}
언급URL : https://stackoverflow.com/questions/41319/checking-if-a-list-is-empty-with-linq
'programing' 카테고리의 다른 글
| SQL 오름차순 정렬 시 null 값이 마지막에 오도록 하는 방법 (0) | 2023.05.09 |
|---|---|
| 메이븐 다운로드에는 .last가 확장으로 업데이트되었습니다. (0) | 2023.05.09 |
| 두 기준의 모든 조합을 반환하면서 여러 기준에 가입하는 방법은 무엇입니까? (0) | 2023.05.09 |
| PostgreSQL에서 데이터베이스 스키마를 내보내려면 어떻게 해야 합니까? (0) | 2023.05.09 |
| WPF 응용 프로그램에서 리소스 '기본 창'을 찾을 수 없습니다.xaml' (0) | 2023.05.09 |