HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcsharpMajor

Sort ObservableCollection after added new item

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
afteritemnewaddedsortobservablecollection

Problem

For a WPF application, I have to sort the items in ObservableCollection after Added new item.

public void UpdateSource(ObservableCollection source, SomeType newItem)
{
    source.Add(newItem);
    SortSource(source, newItem);
}

private void SortSource(ObservableCollection source, SomeType item)
{
    var oldIndex = source.IndexOf(item);
    var list = source.OrderBy(_=>_.SomeProperty).ToList();
    var newIndex = list.IndexOf(item);

    source.Move(oldIndex, newIndex);
}


In order to keep the observable functionality for binding element, the ObservableCollection reference cannot be changed, so I used an assistance list to help me sort the souce.

Any improvement about this?

Solution

Your code unnecessarily sorts the whole collection on each insert (which is likely going to be O(n log n)). It also produces two events for each insert (one for Add and one for Move), which also isn't necessary.

What I would do:

  • Find the index where the inserted item belongs.



  • Insert the item at that index.



A simple implementation for that could look like this:

public static void AddSorted(this IList list, T item, IComparer comparer = null)
{
    if (comparer == null)
        comparer = Comparer.Default;

    int i = 0;
    while (i < list.Count && comparer.Compare(list[i], item) < 0)
        i++;

    list.Insert(i, item);
}


This could be made faster by using binary search to find the index. Though the total complexity is still going to be O(n), even with binary search, because Insert is O(n) (it has to move all items after the inserted item).

This means that using binary search would help the most if you're often inserting items at or near the end of the collection.

Other notes about your code:

public void UpdateSource(ObservableCollection source, SomeType newItem)


I don't think Update is the right name here, this is not a general update, something like AddToSource would be better.

source.OrderBy(_=>_.SomeProperty)


_ as a parameter name of a lambda is commonly used when you don't care about the value of that parameter. If you do care about it (like here), use something like x, or, even better, a meaningful name.

Code Snippets

public static void AddSorted<T>(this IList<T> list, T item, IComparer<T> comparer = null)
{
    if (comparer == null)
        comparer = Comparer<T>.Default;

    int i = 0;
    while (i < list.Count && comparer.Compare(list[i], item) < 0)
        i++;

    list.Insert(i, item);
}
public void UpdateSource(ObservableCollection<SomeType> source, SomeType newItem)
source.OrderBy(_=>_.SomeProperty)

Context

StackExchange Code Review Q#37208, answer score: 31

Revisions (0)

No revisions yet.