IEnumerable <string>을 정렬하는 방법


98

IEnumerable<string>알파벳순으로 정렬하려면 어떻게해야합니까 ? 이게 가능해?

편집 : 내부 솔루션을 어떻게 작성합니까?

답변:


155

다른 열거 형을 정렬하는 것과 같은 방식으로 :

var result = myEnumerable.OrderBy(s => s);

또는

var result = from s in myEnumerable
             orderby s
             select s;

또는 (대소 문자 무시)

var result = myEnumerable.OrderBy(s => s,
                                  StringComparer.CurrentCultureIgnoreCase);

LINQ에서 평소처럼 이렇게하면 열거 될 때 원래 IEnumerable <T>의 요소를 정렬 된 순서로 반환하는 새 IEnumerable <T>가 생성됩니다. IEnumerable <T>를 제자리에 정렬하지 않습니다.


IEnumerable <T>는 읽기 전용입니다. 즉, 요소를 검색 만 할 수 있지만 직접 수정할 수는 없습니다. 문자열 컬렉션을 제자리에서 정렬하려면 먼저 IEnumerable <string>을 구현하는 원래 컬렉션을 정렬하거나 IEnumerable <string>을 정렬 가능한 컬렉션으로 먼저 전환해야합니다.

List<string> myList = myEnumerable.ToList();
myList.Sort();

귀하의 의견에 따라 :

_components = (from c in xml.Descendants("component")
               let value = (string)c
               orderby value
               select value
              )
              .Distinct()
              .ToList();

또는

_components = xml.Descendants("component")
                 .Select(c => (string)c)
                 .Distinct()
                 .OrderBy(v => v)
                 .ToList();

또는 (나중에 목록에 항목을 더 추가하고 정렬 된 상태로 유지하려는 경우)

_components = xml.Descendants("component")
                 .Select(c => (string)c)
                 .Distinct()
                 .ToList();

_components.Add("foo");
_components.Sort();

또는 myEnumerable.OrderByDescending (s => s).
Grozz

따라서 _components = _components.OrderBy (s => s); 괜찮을까요?
CatZilla

@CatZilla : 작동하지만 실제 문제를 해결하는 가장 좋은 방법은 아닐 수 있습니다. _components는 무엇이며, 어디서 얻습니까, 어떻게 사용합니까?
dtb

1
@dtb : 오, _components는 정확히 다음과 같은 방식으로 XML 파일에서 채워집니다. _components = (from c in xml.Descendants ( "component") select c.Value.ToString ()). Distinct (). ToList (); 그리고 그것을 분류해야합니다.
CatZilla

2
OrderBy를 반환합니다 IOrderedEnumerable<T>. IOrderedEnumerable<T>에서 파생 IEnumerable<T>되므로처럼 사용할 수 IEnumerable<T>있지만 유형을 확장하여 예를 들어 ThenBy.
Maciej Hehl

12

불가능하지만 그렇지 않습니다.

기본적으로, 어떤 종류의 방법은 당신을 복사하는 것입니다 IEnumerable으로 List정렬, List다음에있는 정렬 된 목록 반환 IEnumerable뿐만 아니라를 IList.

즉,의 "무한히 계속"속성을 잃었 IEnumerable지만 어쨌든 그런 식으로 정렬 할 수 없습니다.


7
맞아. IEnumerable의 목적은 "다음"항목을 ​​계속 요청하여 처음부터 끝까지 반복 할 수있는 시리즈에 대한 핸들을 제공하는 것입니다. 이는 모든 내용이 알려지기 전에 IEnumerable이 부분적으로 반복 될 수 있음을 의미합니다. 당신이 할 때까지 당신이 그것들을 모두 겪었을 때 알 필요가 없습니다. 정렬 (Linq에서 할 수있는 많은 작업과 마찬가지로)에는 전체 시리즈에 대한 지식이 순서대로 나열되어 있어야합니다. 정렬 된 시리즈에서 첫 번째로 표시되는 항목은 시리즈에서 반환 한 마지막 항목 일 수 있으며 모든 항목이 무엇인지 알지 못하면 알 수 없습니다.
KeithS


2

항상 제자리에서 할 수는 없지만 가능한 경우 감지합니다.

IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, IComparer<T> cmp)
{
  List<T> listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
  listToSort.Sort(cmp);
  return listToSort;
}
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, Comparison<T> cmp)
{
  return SortInPlaceIfCan(src, new FuncComparer<T>(cmp));
}
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src)
{
  return SortInPlaceIfCan(src, Comparer<T>.Default);
}

이것은 다음과 같은 편리한 구조체를 사용합니다.

internal struct FuncComparer<T> : IComparer<T>
{
  private readonly Comparison<T> _cmp;
  public FuncComparer(Comparison<T> cmp)
  {
      _cmp = cmp;
  }
  public int Compare(T x, T y)
  {
      return _cmp(x, y);
  }
}

이걸 추천할지 모르겠어요. IEnumerable <T>가 있지만 구현하는 실제 형식을 모르는 경우 수정해서는 안됩니다. Btw, Array.FunctorComparer <T>는 내부입니다.
dtb

우리가 가지고있는 것을 수정할 때, 나는 제자리를 찾는 질문에 그것을 암시했습니다. 그것을 의미합니다. 메서드 이름에 "InPlaceInCan"이있는 이유입니다. 메소드 이름은 최고의 문서보다 위험에 대해 훨씬 더 앞당길 수 있습니다.) 예, Array.FunctorComparer <T>는 내부적이지만 사소합니다. "헬퍼 클래스 집합에있는 펑터 비교 자"에 대한 예제에서 생각할 수있는 가장 좋은 방법이기 때문에 삽입했습니다.
Jon Hanna

내 자신의 사용하도록 변경, 다른 생각에 @dtb (다시 Array.FunctorComparer에 걸린 모양을하고 어쨌든 내 좋아!)
존 한나에게

똑똑한 아이디어와 이름 지정! 그러나 이중 주조 방지 패턴 은 왜 listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);? 처럼 가지고 무엇에 대해listToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);
제론 Wiert Pluimers

1
@JeroenWiertPluimers 예제 코드에도 항상 문제가 있습니다. 위의 내용이 약간 짧아서 신경 쓰지 않았을 수도 있고, 손에 들고있는 문제에 집중하고 싶었지만, 예를 들어도 나쁜 습관을 억제하는 것이 좋습니다.
Jon Hanna
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.