태그 보관물: linq

linq

linq가 표면에 나타나는 것보다 더 효율적입니까? .Where(x => x.IsSomeValue)

이런 식으로 쓰면 :

var things = mythings
    .Where(x => x.IsSomeValue)
    .Where(y => y.IsSomeOtherValue)

이것은 다음과 같습니다.

var results1 = new List<Thing>();
foreach(var t in mythings)
    if(t.IsSomeValue)
        results1.Add(t);

var results2 = new List<Thing>();
foreach(var t in results1)
    if(t.IsSomeOtherValue)
        results2.Add(t);

또는 다음과 같이 작동하는 표지 아래에 마술이 있습니까?

var results = new List<Thing>();
foreach(var t in mythings)
    if(t.IsSomeValue && t.IsSomeOtherValue)
        results.Add(t);

아니면 완전히 다른 것입니까?



답변

LINQ 쿼리는 지연 됩니다. 그것은 코드를 의미합니다 :

var things = mythings
    .Where(x => x.IsSomeValue)
    .Where(y => y.IsSomeOtherValue);

거의하지 않습니다. 원래 열거 형 ( mythings)은 결과 열거 형 ( things)이 예를 들어 foreach루프 .ToList(), 또는로 소비 될 때만 열거됩니다 .ToArray().

를 호출하면 things.ToList()후자의 코드와 대략 동일하며 열거 자에서 약간의 (일반적으로 중요하지 않은) 오버 헤드가 있습니다.

마찬가지로 foreach 루프를 사용하는 경우 :

foreach (var t in things)
    DoSomething(t);

성능면에서 다음과 유사합니다.

foreach (var t in mythings)
    if (t.IsSomeValue && t.IsSomeOtherValue)
        DoSomething(t);

열거 형에 대한 게으름 접근 방식의 성능 이점 중 일부는 (모든 결과를 계산하고 목록에 저장하는 것과는 대조적으로) 메모리를 거의 사용하지 않으며 (한 번에 하나의 결과 만 저장되므로) 중요한 것은 없습니다 초기 비용.

열거 형이 부분적으로 만 열거되는 경우 특히 중요합니다. 이 코드를 고려하십시오.

things.First();

LINQ가 구현되는 방식은 mythings위치 조건과 일치하는 첫 번째 요소까지만 열거됩니다. 해당 요소가 목록에서 일찍 나오는 경우 성능이 크게 향상 될 수 있습니다 (예 : O (n) 대신 O (1)).


답변

다음 코드 :

var things = mythings
    .Where(x => x.IsSomeValue)
    .Where(y => y.IsSomeOtherValue);

게으른 평가로 인해 아무것도 발생하지 않습니다.

var things = mythings
    .Where(x => x.IsSomeValue)
    .Where(y => y.IsSomeOtherValue)
    .ToList();

평가가 시작되기 때문에 다릅니다.

의 각 항목은 mythings첫 번째에 제공 Where됩니다. 통과하면 두 번째에 제공 Where됩니다. 통과하면 출력의 일부가됩니다.

그래서 이것은 다음과 같이 보입니다 :

var results = new List<Thing>();
foreach(var t in mythings)
{
    if(t.IsSomeValue)
    {
        if(t.IsSomeOtherValue)
        {
            results.Add(t);
        }
    }
}

답변

지연 된 실행은 제쳐두고 (다른 답변은 이미 설명했지만 다른 세부 사항을 지적하겠습니다) 두 번째 예와 비슷합니다.

그냥 당신이 전화를 가정 해 봅시다 ToListthings.

의 구현 Enumerable.Where은를 반환합니다 Enumerable.WhereListIterator. 당신이 호출하면 Where그에 WhereListIterator(일명 체인 Where, 당신은 더 이상 전화 -calls) Enumerable.Where하지만, Enumerable.WhereListIterator.Where실제로 조건을 결합, (사용 Enumerable.CombinePredicates).

그래서 더 비슷 if(t.IsSomeValue && t.IsSomeOtherValue)합니다.


답변

아니요 동일하지 않습니다. 당신의 예에서 thingsIEnumerable이 시점에서 여전히 반복자가 아닌 실제 배열이나리스트이다. 또한 things사용되지 않으므로 루프는 평가되지 않습니다. 이 유형을 IEnumerable사용하면 yieldLinq 명령어에 의해 -ed 요소를 반복 하고 더 많은 명령어로 더 처리 할 수 ​​있습니다. 결국에는 실제로 하나의 루프 만 있습니다.

그러나 즉시로 같은 명령을 추가 .ToArray()하거나 .ToList()당신이 따라서, 실제 데이터 구조의 생성을 주문하여 체인에 경계를두고있어.

이 관련 SO 질문을 참조하십시오 : https : //.com/questions/2789389/how-do-i-implement-ienumerable


답변