C# Array sort question

Associate
Joined
30 Mar 2004
Posts
1,148
Location
West Wing
Hi,

I have an array of strings like this:

List<string> myList = new List<string>();
myList.add("Samuel, 01/09/2014");
myList.add("David, 15/08/2014");
myList.add("Alan, 19/08/2014");
myList.add("Ellen, 03/07/2014");
myList.add("Alan, 20/08/2014");

What i want to do is sort the array alphabetically by the name in the first part of the string without losing the associated date information.

Hope that makes sense, not sure if im going about this in the best way. Should i be using a different type of array? Or maybe create 2 separate arrays?

Appreciate any advice :)
 
Soldato
Joined
16 Feb 2004
Posts
4,811
Location
London
in that example you just need to call myList.Sort(); to sort it a-z. It works because you are storing all the information inside one string.

A more OO way would be to make up an object with separate parameters like this.

Code:
List<Person> people = new List<Person>();
people.Add(new Person("Samuel", new DateTime(2014, 9, 1)));
people.Add(new Person("David", new DateTime(2014, 8, 15)));
people.Add(new Person("Alan", new DateTime(2014, 8, 19)));
people.Add(new Person("Ellen", new DateTime(2014, 7, 3)));
people.Add(new Person("Alan", new DateTime(2014, 8, 20)));

people.Sort((x, y) => x.Name.CompareTo(y.Name));

public class Person
{
	public string Name {get;set;}
	public DateTime DOB {get;set;}
	
	public Person(string name, DateTime dob)
	{
		Name = name;
		DOB = dob;
	}
}
 
Associate
Joined
16 Apr 2007
Posts
2,208
in that example you just need to call myList.Sort(); to sort it a-z. It works because you are storing all the information inside one string.

A more OO way would be to make up an object with separate parameters like this.

Code:
List<Person> people = new List<Person>();
people.Add(new Person("Samuel", new DateTime(2014, 9, 1)));
people.Add(new Person("David", new DateTime(2014, 8, 15)));
people.Add(new Person("Alan", new DateTime(2014, 8, 19)));
people.Add(new Person("Ellen", new DateTime(2014, 7, 3)));
people.Add(new Person("Alan", new DateTime(2014, 8, 20)));

people.Sort((x, y) => x.Name.CompareTo(y.Name));

public class Person
{
	public string Name {get;set;}
	public DateTime DOB {get;set;}
	
	public Person(string name, DateTime dob)
	{
		Name = name;
		DOB = dob;
	}
}

Basically this, if you continue with the just having it as one string and doing .sort() you will get some oddities if there are people with the same name as the DOB will be sorted alphabetically not numerically.
 
Associate
OP
Joined
30 Mar 2004
Posts
1,148
Location
West Wing
Thanks, i didn't think of using the sort function.

Another question, how do I remove duplicates from the array? You can see in my first example there are 2 Alans.
 
Associate
Joined
16 Apr 2007
Posts
2,208
Thanks, i didn't think of using the sort function.

Another question, how do I remove duplicates from the array? You can see in my first example there are 2 Alans.

Do you want to remove duplicates even if the DOB is not the same?
If you want to remove 2 items that are the same

myList = myList.ToDistinct().ToList() should do that.
 
Associate
OP
Joined
30 Mar 2004
Posts
1,148
Location
West Wing
I want to remove items that have the same name only. I.e. remove the second Alan, even though the date is different to the first Alan.
 

AJK

AJK

Associate
Joined
8 Sep 2009
Posts
1,722
Location
UK
Thanks, i didn't think of using the sort function.

Another question, how do I remove duplicates from the array? You can see in my first example there are 2 Alans.

You don't have any duplicates in your list, because the strings are not the same (the two Alans have different dates of birth). You really do NOT want to be storing names and dates of birth as a single string, in the way you describe in your original post, if your intention is to perform any kind of action (sorting, de-duplicating, etc.) on the names and dates separately.

Also you're not using an Array, you're using a List - these are two different data structures, and will fundamentally affect the way you do everything you're asking about.
 
Soldato
Joined
16 Feb 2004
Posts
4,811
Location
London
Also you're not using an Array, you're using a List - these are two different data structures, and will fundamentally affect the way you do everything you're asking about.

yep, using the List collection types is much nicer in c# than using arrays, they provide more features and are easier to work with. Once you've learnt all the basics then you can start to pick specific collection types where it makes sense to improve performance etc.

There's a cool program you can download to help learn all the object types

http://www.linqpad.net/

Change the top language dropdown to C# program and copy this in

Code:
void Main()
{
	List<Person> people = new List<Person>();
	people.Add(new Person("Samuel", new DateTime(2014, 9, 1)));
	people.Add(new Person("David", new DateTime(2014, 8, 15)));
	people.Add(new Person("Alan", new DateTime(2014, 8, 19)));
	people.Add(new Person("Ellen", new DateTime(2014, 7, 3)));
	people.Add(new Person("Alan", new DateTime(2014, 8, 20)));
	
	people = people.Distinct().ToList();
	
	people.Sort((x, y) => x.Name.CompareTo(y.Name));
	
	people.Dump();
}

public class Person
{
	public string Name {get;set;}
	public DateTime DOB {get;set;}
	
	public Person(string name, DateTime dob)
	{
		Name = name;
		DOB = dob;
	}
}

and you'll end up with this in the result window

13zbvjp.jpg
 
Last edited:
Caporegime
Joined
18 Oct 2002
Posts
29,491
Location
Back in East London
You can overload the Disctinct() method if you want to, as well.

Code:
people.Distinct(p => p.Name)

edit: Ugh. This what I get for not actually checking before posting:

The above overload doesn't exist, which is quite a surprise. You'd need to provide an implementation of IEqualityComparer<Person> instead of the lambda like that in my example above.
 
Last edited:
Associate
Joined
16 Apr 2007
Posts
2,208
You can overload the Disctinct() method if you want to, as well.

Code:
people.Distinct(p => p.Name)

edit: Ugh. This what I get for not actually checking before posting:

The above overload doesn't exist, which is quite a surprise. You'd need to provide an implementation of IEqualityComparer<Person> instead of the lambda like that in my example above.
I was going to post the exact same thing and thought Id double check
Found this though to do it in 1 line
myList.GroupBy(p => p.Name).Select(grp => grp.First());
 
Soldato
Joined
18 Oct 2002
Posts
3,926
Location
SW London
It's really annoying - inexplicable - that Distinct() can't take the same lambda expression as most other similar LINQ operations.

MoreLINQ adds method DistinctBy() which does allow it:
https://www.nuget.org/packages/morelinq/1.1.0

There's also the Interactive Extensions which provide a similar thing.

It was written by the Reactive Extensions team at Microsoft and basically adds various extension methods to Linq to objects to give the same methods over enumerables as Rx provides for observables.
 
Back
Top Bottom