2013-06-12 2 views
0

죄송하지만 내 질문에 많은 코드를 고수해야 할 것 같습니다. 좋은 소식은 시간이 있다면 콘솔 응용 프로그램에이 파일을 복사하여 실행하면 결과와 함께 문제를 볼 수 있습니다.예기치 않은 순서로 IComparabale이 정렬됩니다.

나는 목록을 받았다. (예, 아래 코드의 목록은 실제로 목록이다!). 본질적으로, 나는 List<string, string>을 줄 것이다. 나는 명확하게하기 위해 List<ColLeft, ColRight>이라고 부를 것이다.

ColLeft는 이미 그룹화되어 있으며 그룹으로 남아 있어야합니다.

ColRight는 알파벳 순서가 아니며 그룹 내에 있어야합니다.

저는 .NET 2.0을 사용 중이므로 IComparable<T>을 구현했습니다. 그러나 목록이 잘못된 순서로 반환됩니다 및 이유는 (동일한 문제가 VS2005 또는 VS2010 실행) 계속 이해할 수 없습니다.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 

namespace SortingLists 
{ 
    class Program 
    { 
     static void Main() 
     { 
      List<ListContents> listContents = ListContents.GetListContents(); 
      WriteOut(listContents); 
      Console.WriteLine("\r\n"); 

      listContents.Sort(); 
      WriteOut(listContents); 
      Console.ReadKey(); 
     } 

     private static void WriteOut(List<ListContents> listContents) 
     { 
      foreach (ListContents content in listContents) 
       Console.WriteLine(content.ColLeft + " --- " + content.ColRight); 
     } 
    } 

    struct ListContents : IComparable<ListContents> 
    { 
    #region Constructor 

    public ListContents(string l, string r) 
    { 
     this.ColLeft = l; 
     this.ColRight = r; 
    } 

    #endregion 

    #region Fields 

    public string ColLeft; 
    public string ColRight; 

    #endregion 

    #region IComparable<ListContents> Members 

    public int CompareTo(ListContents other) 
    { 
     if (this.ColLeft.CompareTo(other.ColLeft) == -1) 
      return this.ColLeft.CompareTo(other.ColLeft); 
     else 
      return this.ColRight.CompareTo(other.ColRight); 
    } 

    #endregion 

    #region Methods 

    public static List<ListContents> GetListContents() 
    { 
     List<ListContents> lcList = new List<ListContents>(); 
     lcList.Add(new ListContents("UFT", "a")); 
     lcList.Add(new ListContents("UFT", "c")); 
     lcList.Add(new ListContents("UFT", "b")); 
     lcList.Add(new ListContents("RT", "f")); 
     lcList.Add(new ListContents("RT", "e"));    
     lcList.Add(new ListContents("RT", "d")); 
     lcList.Add(new ListContents("UT", "m")); 
     lcList.Add(new ListContents("UT", "o")); 
     lcList.Add(new ListContents("UT", "n"));    
     return lcList; 
    } 
} 

그래도 난 그것을 해결할 수 - 내가 뭔가 등을() GetListContents의 순서를 변경하면 ... 원하는대로

public static List<ListContents> GetListContents() 
    { 
     List<ListContents> lcList = new List<ListContents>(); 
     lcList.Add(new ListContents("UFT", "a")); 
     lcList.Add(new ListContents("UFT", "c")); 
     lcList.Add(new ListContents("UFT", "b")); 
     lcList.Add(new ListContents("RT", "e")); 
     lcList.Add(new ListContents("RT", "f"));//Moved this item 
     lcList.Add(new ListContents("RT", "d")); 
     lcList.Add(new ListContents("UT", "m")); 
     lcList.Add(new ListContents("UT", "o")); 
     lcList.Add(new ListContents("UT", "n"));    
     return lcList; 
    } 

이 ... 그런 결과가 나올. 분명히 List가 어떤 순서로 올지 예측할 수 없기 때문에 이것은 수정 사항이 아닙니다. 유일한 상수는 ColLeft가 그룹화되어 있다는 것입니다.

아무도 내가이 동작을 이해하는 데 도움이 될 수 있습니까?

답변

1

어디서나 원래 주문을 보존하지 않았기 때문에 목록이 잘못된 순서로 반환됩니다. 다음과 같이 LINQ (.NET 3.x의) 당신은 그것을 할 수 :

list.GroupBy(x => x.LeftCol) 
    .Select(g => g.OrderBy(x => x.RightCol)) 
    .SelectMany(x => x) 
    .ToList(); 

.NET 2.0에서 비슷한 일을해야 할 것입니다; 즉 첫 번째 그룹을 LeftCol로 정렬 한 다음 RightCol로 각 그룹을 정렬 한 다음 그룹을 연결합니다.

예를 들어 ListContents 클래스를 제어하는 ​​경우 보존 할 주문을 나타내는 int Index 필드를 추가 할 수 있습니다 (첫 번째 그룹은 0, 두 번째 그룹은 1 등). 그런 다음 RightCol에 의해 다음, Index에 의해 처음으로 비교하는 비교자를 사용하여 정렬 : 당신이 ListContents 클래스를 수정하지 않으려면

int index = 0; 
for(int i=0; i<list.Count; i++) 
{ 
    if (i > 0 && list[i].LeftCol != list[i - 1].LeftCol) index++; 
    list[i].Index = index; 
} 

... 

public int CompareTo(ListContents other) 
{ 
    int result = this.Index.CompareTo(other.Index); 
    if (result != 0) return result; 
    return this.ColRight.CompareTo(other.ColRight); 
} 

, 당신은 정렬하기 전에 Tuple<int, ListContents>의 각 항목을 포장하여 비슷한 일을 할 수 있습니다.

관련 문제