[C#] LINQ로 주문 유지

정렬 된 배열에서 LINQ to Objects 명령어를 사용합니다. 배열 순서가 변경되지 않도록하려면 어떤 작업을 수행하지 않아야합니까?



답변

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


답변

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

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

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


답변

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

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

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

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


답변

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

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

에서 Enumerable.GroupBy의 문서 :

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

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

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


답변

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


답변

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

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

mysqlresult.OrderBy(e=>e.SomeColumn)

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


답변