LINQ로 주문 유지


답변:


645

비 IEnumerable 결과를 반환 한 모든 것을 버리고 System.Linq.Enumerable 의 메서드를 검사했습니다 . 결과의 순서가 소스의 순서와 어떻게 다른지 결정하기 위해 각각의 설명을 확인했습니다.

절대적으로 주문을 유지합니다. 소스 요소를 색인별로 결과 요소에 맵핑 할 수 있습니다.

  • 무수히
  • 캐스트
  • 연결
  • 고르다
  • ToArray
  • ToList

주문을 유지합니다. 요소는 필터링되거나 추가되지만 순서는 변경되지 않습니다.

  • 뚜렷한
  • 교차
  • OfType
  • 접두사 (.net 4.7.1의 새로운 기능)
  • 건너 뛰기
  • 건너 뛰기
  • 갖다
  • 가져가는 동안
  • 어디
  • Zip (.net 4의 새로운 기능)

주문 제거-결과가 어떤 순서로 나올지 알 수 없습니다.

  • 사전
  • 찾아보다

순서를 명시 적으로 재정의-이를 사용하여 결과 순서를 변경합니다

  • 주문
  • OrderByDescending
  • 역전
  • 그런 다음
  • 그럼 내림차순

일부 규칙에 따라 순서를 재정의하십시오.

  • GroupBy-IGrouping 오브젝트는 각 IGrouping의 첫 번째 키를 생성 한 소스의 요소 순서에 따라 순서대로 생성됩니다. 그룹화의 요소는 소스에 나타나는 순서대로 생성됩니다.
  • GroupJoin-GroupJoin은 외부 요소의 순서를 유지하고 외부의 각 요소에 대해 내부에서 일치하는 요소의 순서를 유지합니다.
  • 결합-외부 요소의 순서를 유지하고 이러한 각 요소에 대해 일치하는 내부 요소의 순서를 유지합니다.
  • SelectMany-소스의 각 요소에 대해 selector가 호출되고 일련의 값이 리턴됩니다.
  • Union-이 메서드에서 반환 된 개체가 열거되면 Union은 첫 번째와 두 번째 순서로 열거하고 아직 생성되지 않은 각 요소를 생성합니다.

편집 :이 구현을 기반으로 Distinct를 Preserving 순서로 옮겼습니다 .

    private static IEnumerable<TSource> DistinctIterator<TSource>
      (IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
    {
        Set<TSource> set = new Set<TSource>(comparer);
        foreach (TSource element in source)
            if (set.Add(element)) yield return element;
    }

2
실제로, 나는 Distinct가 원래 (처음 발견 된) 순서를 유지한다고 생각합니다. 따라서 {1,2,1,3,1,3,4,1,5}는 {1,2,3,4,5}입니다
Marc Gravell

10
msdn.microsoft.com/ko-kr/library/bb348436.aspx Distinct <(Of <(TSource>)>) (IEnumerable <(Of <(TSource>)>)) 메서드는 중복 값이없는 순서가없는 순서를 반환합니다. .
Amy B

12
마크 : 당신이 말하는 것은 사실 일 수 있지만, 그 행동에 의존하는 것은 나쁜 생각입니다.
Amy B

4
@Amy B 예. Linq to Objects에는 적용되지 않습니다. Linq to Sql에서 distinct ()는 distinct 키워드를 생성 된 sql에 넣고 sql에서의 순서는 보장되지 않습니다. 순서를 유지하지 않고 순서를 유지하는 것보다 효율적인 객체에 대한 linq에 대한 뚜렷한 구현을보고 싶습니다. 예를 들어, 전체 입력을 소비하여 해시 세트에 넣은 다음 해시 세트 (손실 순서)를 열거하여 값을 산출 할 수 있지만 더 나쁩니다. 그렇습니다, 나는 때때로 문서를 무시하는 것을 좋아하지 않습니다. :)
dan

4
어쩌면 문서 ( Distinct방법에 대한 )는 "예측할 수없는 순서로"가 아니라 "정렬되지 않은"이라고 말하는 것일 수도 있습니다. Distinct위와 같이 위의 필터링 범주에 속 한다고 말하고 싶습니다 Where.
Jeppe Stig Nielsen

34

실제로 SQL 또는 배열에 대해 이야기하고 있습니까? 다시 말하면 LINQ to SQL 또는 LINQ to Objects를 사용하고 있습니까?

LINQ to Objects 연산자는 실제로 원래 데이터 소스를 변경하지 않고 데이터 소스가 효과적으로 지원하는 시퀀스를 만듭니다. 순서를 변경하는 유일한 작업은 OrderBy / OrderByDescending / ThenBy / ThenByDescending입니다. 심지어 동일한 순서의 요소에 대해서도 안정적입니다. 물론 많은 작업에서 일부 요소를 필터링하지만 반환되는 요소는 동일한 순서로 정렬됩니다.

ToLookup 또는 ToDictionary와 같은 다른 데이터 구조로 변환하면 그 시점에서 순서가 유지되지 않는다고 생각하지만 어쨌든 다소 다릅니다. (하지만 동일한 키에 매핑되는 값의 순서는 조회를 위해 유지됩니다.)


따라서 OrderBy는 안정적인 정렬이므로 seq.OrderBy (_ => _.Key)는 요소를 seq.GroupBy (_ => _.Key)와 정확히 동일한 순서로 배치합니다. ). 그 맞습니까?
dmg

1
@ dmg : 아니오, 그렇지 않습니다. 바로 GroupBy뒤에는 SelectMany키별로 결과가 그룹화되지만 오름차순 키 순서는 제공되지 않습니다 ... 키가 원래 발생한 순서대로 결과가 표시됩니다.
Jon Skeet

LINQ to SQL은 순서를 유지하지 않는다고 말하는가?
symbiont

@symbiont : 많은 SQL 작업에서 잘 정의 된 순서 없습니다. 기본적으로 나는 LINQ to Objects와 같이 내가 보장 할 수있는 것들에 대해서만 약속하려고합니다.
Jon Skeet

@JonSkeet OrderBy를 사용하면 동일한 키를 가진 'n'개체가 모두 함께 있다는 것을 제외하고는 원래 순서를 유지합니다. 즉, list<x> {a b c d e f g}만약 c, d, e가 모두 같은 키를 가지면 결과 시퀀스는 c, d, e를 나란히 그리고 c, d, e 순서로 포함 할 것이다. 범주 형 MS 기반 답변을 찾지 못하는 것 같습니다.
Paulustrious

7

배열에서 작업하는 경우 SQL이 아닌 LINQ-to-Object를 사용하는 것처럼 들립니다. 확인 할수 있어요? 대부분의 LINQ 연산은 순서를 바꾸지 않습니다 (출력은 입력과 순서가 동일 함). 따라서 다른 정렬을 적용하지 마십시오 (OrderBy [Descending] / ThenBy [Descending]).

[편집 : Jon이 더 명확하게 말하면; LINQ는 일반적으로 원본 데이터 만 남겨두고 새로운 시퀀스를 만듭니다. ]

Dictionary<,>사전이 특정 정렬 순서를 따르지 않기 때문에 데이터를 (ToDictionary) 로 푸시하면 데이터 가 스크램블됩니다.

그러나 가장 일반적인 것 (Select, Where, Skip, Take)은 괜찮습니다.


내가 실수하지 않으면 ToDictionary()단순히 주문에 대해 약속 하지 않지만 실제로는 입력 주문을 유지합니다 (당신이 주문을 제거 할 때까지). 나는 이것에 의존한다고 말하지는 않지만 '스크램블링'은 정확하지 않은 것 같습니다.
Timo

4

공식 문서를 참조하는 비슷한 질문에서 큰 대답을 찾았습니다. 인용하려면 :

들어 Enumerable방법 (적용 객체에 LINQ, List<T>), 당신은에 의해 반환 된 요소의 순서에 의존 할 수 있습니다 Select, Where또는 GroupBy. 이것은 본질적으로 ToDictionaryor 와 같이 순서가 정돈되지 않은 것들에는 해당되지 않습니다 Distinct.

에서 Enumerable.GroupBy의 문서 :

IGrouping<TKey, TElement>개체는 각각의 첫번째 키를 생성 소스의 요소의 순서에 따라 순서대로 산출된다 IGrouping<TKey, TElement>. 그룹화의 요소는에 표시된 순서대로 산출됩니다 source.

IQueryable확장 방법 (다른 LINQ 공급자) 에는 반드시 해당되는 것은 아닙니다 .

출처 : LINQ의 열거 가능한 방법은 요소의 상대적 순서를 유지합니까?


2

'group by'또는 'order by'는 순서를 변경할 수 있습니다.


0

여기서 질문은 구체적으로 LINQ-to-Objects를 나타냅니다.

LINQ-to-SQL을 대신 사용하는 경우 다음과 같은 명령을 적용하지 않으면 순서가 없습니다.

mysqlresult.OrderBy(e=>e.SomeColumn)

LINQ-to-SQL을 사용하여이 작업을 수행하지 않으면 동일한 쿼리 데이터라도 후속 쿼리간에 결과 순서가 달라질 수 있으며 간헐적 인 버그가 발생할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.