Pages

Showing posts with label Collections. Show all posts
Showing posts with label Collections. Show all posts

Thursday, 29 January 2009

Sorting and De-duping arrays

I seem to be obsessed with sorting based on the number of posts I've made on the topic.
Sorting a simple string[] is easy using:

string[] recordIds = { "q", "z", "a", "b", "q" };
 
Array.Sort(recordIds);

To stop a third party component from failing we had to ensure that our string[] array contained only unique strings. Sorting and de-duping using LINQ could be done in a single line:

string[] recordIds = { "q", "z", "a", "b", "q" };
 
var sortedUniqueIds = (from id in recordIds orderby id select id).Distinct();
 
int i=0;
foreach (string id in sortedUniqueIds)
{
   recordIds[i++] = id;
}

Microsoft have an excellent LINQ samples page: 101 LINQ Samples

Tuesday, 27 January 2009

Sorting Generic Collections - Redux

Using LINQ it turns out to be quite easy to sort a generic Dictionary by either Key or Value.

In these examples a list of sorted keys is returned in the 'keys' variable.

Alternately the LINQ statement can used directly in a foreach loop.

Dictionary<string, string> dict = new Dictionary<string, string>();
...


// Sort by Key
var keys = from key in dict.Keys orderby key ascending select key;


// Sort by Value
var keys = from key in dict.Keys orderby dict[key] ascending select key;


// Sort within foreach(...) by Key
foreach(string aKey in (from key in dict.Keys orderby key ascending select key)){
...
}

Friday, 17 October 2008

ObservableCollection<T>.CollectionChanged

According to the documentation: "This event occurs when an item is added, removed, changed, moved or the entire list is refreshed."

However it does not occur if a property on an object in the collection changes, even if that object implements the INotifyPropertyChanged.

The new value of the object's property is reflected in the UI automatically (as you would expect of an ObservableCollection).

I wanted to know that something inside the collection had changed so that I could set a HasChanges property on the Model that the UI is bound to via its ObjectDataProvider. The intention was then to have a visual clue on the UI that was bound to the HasChanges property.

This posting doesn't have a solution, its simply a reminder not to try to use this event for this purpose in the future.

Monday, 6 October 2008

Sorting a collection using Linq and 'SortExpression' string

Bruce suggested that we use LINQ to sort collections. I found the following code on Miron Abrahason's blog but haven't had the chance to try it out yet.

Already happened to you that you had a collection of object from type 'X' with some properties, and you had to sort it one time by property 'ID', and another time by property 'Name' ? You wished that you can sort it by just using a 'Sort Expression' ? If still not, I'm sure this moment will arrive sooner or later. Let me save you some time and an headache.

This is how it can be done:

public static IEnumerable Sort(this IEnumerable source, string sortExpression)
{
string[] sortParts = sortExpression.Split(' ');
var param = Expression.Parameter(typeof(T), string.Empty);
try
{
var property = Expression.Property(param, sortParts[0]);
var sortLambda = Expression.Lambda>(Expression.Convert(property, typeof(object)), param);
if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
{
return source.AsQueryable().OrderByDescending(sortLambda);
}
return source.AsQueryable().OrderBy(sortLambda);
}
catch (ArgumentException)
{
return source;
}
}

Just drop it in a static class, and you will be able to sort any collection that implement the interface IEnumerable.

Lets say you have a class 'User':
public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
}

and a List collection: users. You can sort it however you want:
IEnumerable sortedUsersIEnumerable = users.Sort("ID desc");

Or
List sortedUsersList = users.Sort("Name").ToList();

Sunday, 5 October 2008

Sorting Generic Collections

You can simplify the sorting by using the anonymous delegate as shown below and you don't need to implement IComparable interface:

(Note: For a simpler technique using LINQ see: Sorting Generic Collections - Redux)
List persons = new List();
persons.Add( new Person("Tom",30) );
persons.Add(new Person("Harry", 55));

// sort in ascending order
persons.Sort( delegate(Person person0, Person person1)
{
return
person0.FirstName.CompareTo(person1.FirstName);
} );


// sort in descending order
persons.Sort( delegate(Person person0, Person person1)
{
return
person1.FirstName.CompareTo(person0.FirstName);
} );