관찰 가능 항목을 정렬하고 정렬 된 동일한 객체를 반환하는 작업은 확장 메서드를 사용하여 수행 할 수 있습니다. 더 큰 컬렉션의 경우 컬렉션 변경 알림 수를주의하세요.
성능을 향상시키고 중복을 처리하기 위해 코드를 업데이트했습니다 (원래 데이터 예제에서는 잘 작동했지만 원본의 성능 저하를 강조한 nawfal에게 감사드립니다). 관찰 가능 항목은 왼쪽으로 정렬 된 절반과 오른쪽으로 정렬되지 않은 절반으로 분할되며, 여기서 최소 항목 (정렬 된 목록에있는)이 정렬되지 않은 파티션에서 정렬 된 파티션의 끝으로 이동 될 때마다 이동합니다. 최악의 경우 O (n). 기본적으로 선택 정렬입니다 (출력은 아래 참조).
public static void Sort<T>(this ObservableCollection<T> collection)
where T : IComparable<T>, IEquatable<T>
{
List<T> sorted = collection.OrderBy(x => x).ToList();
int ptr = 0;
while (ptr < sorted.Count - 1)
{
if (!collection[ptr].Equals(sorted[ptr]))
{
int idx = search(collection, ptr+1, sorted[ptr]);
collection.Move(idx, ptr);
}
ptr++;
}
}
public static int search<T>(ObservableCollection<T> collection, int startIndex, T other)
{
for (int i = startIndex; i < collection.Count; i++)
{
if (other.Equals(collection[i]))
return i;
}
return -1; // decide how to handle error case
}
사용법 : 관찰자가있는 샘플 (단순하게 유지하기 위해 Person 클래스 사용)
public class Person:IComparable<Person>,IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Person other)
{
if (this.Age == other.Age) return 0;
return this.Age.CompareTo(other.Age);
}
public override string ToString()
{
return Name + " aged " + Age;
}
public bool Equals(Person other)
{
if (this.Name.Equals(other.Name) && this.Age.Equals(other.Age)) return true;
return false;
}
}
static void Main(string[] args)
{
Console.WriteLine("adding items...");
var observable = new ObservableCollection<Person>()
{
new Person {Name = "Katy", Age = 51},
new Person {Name = "Jack", Age = 12},
new Person {Name = "Bob", Age = 13},
new Person {Name = "Alice", Age = 39},
new Person {Name = "John", Age = 14},
new Person {Name = "Mary", Age = 41},
new Person {Name = "Jane", Age = 20},
new Person {Name = "Jim", Age = 39},
new Person {Name = "Sue", Age = 5},
new Person {Name = "Kim", Age = 19}
};
//what do observers see?
observable.CollectionChanged += (sender, e) =>
{
Console.WriteLine(
e.OldItems[0] + " move from " + e.OldStartingIndex + " to " + e.NewStartingIndex);
int i = 0;
foreach (var person in sender as ObservableCollection<Person>)
{
if (i == e.NewStartingIndex)
{
Console.Write("(" + (person as Person).Age + "),");
}
else
{
Console.Write((person as Person).Age + ",");
}
i++;
}
Console.WriteLine();
};
컬렉션이 피벗되는 방식을 보여주는 정렬 진행률 세부 정보 :
Sue aged 5 move from 8 to 0
(5),51,12,13,39,14,41,20,39,19,
Jack aged 12 move from 2 to 1
5,(12),51,13,39,14,41,20,39,19,
Bob aged 13 move from 3 to 2
5,12,(13),51,39,14,41,20,39,19,
John aged 14 move from 5 to 3
5,12,13,(14),51,39,41,20,39,19,
Kim aged 19 move from 9 to 4
5,12,13,14,(19),51,39,41,20,39,
Jane aged 20 move from 8 to 5
5,12,13,14,19,(20),51,39,41,39,
Alice aged 39 move from 7 to 6
5,12,13,14,19,20,(39),51,41,39,
Jim aged 39 move from 9 to 7
5,12,13,14,19,20,39,(39),51,41,
Mary aged 41 move from 9 to 8
5,12,13,14,19,20,39,39,(41),51,
Person 클래스는 IComparable과 IEquatable을 모두 구현합니다. 후자는 발생하는 변경 알림의 수를 줄이기 위해 컬렉션의 변경을 최소화하는 데 사용됩니다.
- 편집 새 복사본을 만들지 않고 동일한 컬렉션을 정렬합니다. *
ObservableCollection을 반환하려면 [this implementation] [1]과 같이 * sortedOC *에서 .ToObservableCollection을 호출합니다.
**** orig answer-이것은 새로운 컬렉션을 생성합니다 **** 아래의 doSort 메소드가 보여주는 것처럼 linq를 사용할 수 있습니다. 빠른 코드 스 니펫 : 생성
3 : xey 6 : fty 7 : aaa
또는 컬렉션 자체에서 확장 메서드를 사용할 수 있습니다.
var sortedOC = _collection.OrderBy(i => i.Key);
private void doSort()
{
ObservableCollection<Pair<ushort, string>> _collection =
new ObservableCollection<Pair<ushort, string>>();
_collection.Add(new Pair<ushort,string>(7,"aaa"));
_collection.Add(new Pair<ushort, string>(3, "xey"));
_collection.Add(new Pair<ushort, string>(6, "fty"));
var sortedOC = from item in _collection
orderby item.Key
select item;
foreach (var i in sortedOC)
{
Debug.WriteLine(i);
}
}
public class Pair<TKey, TValue>
{
private TKey _key;
public TKey Key
{
get { return _key; }
set { _key = value; }
}
private TValue _value;
public TValue Value
{
get { return _value; }
set { _value = value; }
}
public Pair(TKey key, TValue value)
{
_key = key;
_value = value;
}
public override string ToString()
{
return this.Key + ":" + this.Value;
}
}