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.