0

I am fairly new to C#

I am trying to retrieve some information from an external data source and store it in array, once it is in an array I wish to sort it by time.

I know how to do this for just one column in a row, however the information I require has multiple columns.

For example:

foreach (Appointment Appoint in fapts)
{
    // Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
} 

// Sort my array by Appoint.Start

foreach ( item in myNewArray ) 
{
    //print out Appoint.Subject - Appoint.Start, Appoint.Organiser.Name.ToString() and Appoint.location
}

Many thanks for your help.

EDIT:

I have multiple data sources which pull in this:

foreach (Appointment Appoint in fapts)
{
    // Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
} 

Hence the need to sort the items in a new array, I know this isn't very efficent but there is no way of getting the information I need in any other way.

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
Corbin Spicer
  • 285
  • 1
  • 8
  • 26

6 Answers6

3

You can sort a list using the LINQ sorting operators OrderBy and ThenBy, as shown below.

using System.Linq;

and then...

var appointments = new List<Appointment>();
var sortedAppointments = list.OrderBy(l => l.Subject).ThenBy(l => l.Name).ToList();

This will create a new list of appointments, sorted by subject and then by name.

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
2

It's unclear what your final aim is but:

Use a generic List instead of an array:

See this SO question for more information as to why using a List is prefered.

List<Appointment> appointments = new List<Appointment>();

foreach (Appointment Appoint in fapts)
{
    appointments.Add(Appoint);
} 

foreach (var item in appointments) 
{
    Console.WriteLine(item.Subject);
    Console.WriteLine(item.Foo);
    // Here you could override ToString() on Appointment to print eveything in one Console.WriteLine
}

If the aim of your code is to order by time, try the following:

var sortedAppointments = fapts.OrderBy(a => a.Start); // assuming Start is a DateTime property of `Appointment`.
Community
  • 1
  • 1
Sam Leach
  • 12,746
  • 9
  • 45
  • 73
  • This is all very well and good but I have multiple foreach statements, one for every room, which is why I need an array in the first place – Corbin Spicer Oct 03 '13 at 08:17
  • -1 not currently correct. `OrderBy` returns an `IEnumerable`, so you can't assign to a list. You use a `for` loop to get from an array to a list, then you don't tell him how a list helps beyond that. – user2586804 Oct 03 '13 at 08:20
  • 1
    Better ways to get from an array to a list: 1. `fapts.ToList();` 2. `new List(fapts);` – user2586804 Oct 03 '13 at 08:23
  • We have no idea what `fapts` is. OP says it is an 'external data source'. @user2586804 I have updated my answer with a link to array vs. List discussion. – Sam Leach Oct 03 '13 at 09:09
  • Thanks Sam, using your answer I've come up with some sort of solution - the order by doesn't seem to be working though appointments.OrderBy(a => a.Start); – Corbin Spicer Oct 03 '13 at 09:31
  • Magic, just got it working foreach (var item in appointments.OrderBy(a => a.Start)) { s = s + "" + item.Subject + "" + "" + item.Start + "" + item.Organizer.Name.ToString() + "" + item.Location + ""; } – Corbin Spicer Oct 03 '13 at 09:33
  • OK Sam, so if we have no idea what it is, how are you using it in a `foreach`? I made no more assumptions than you. – user2586804 Oct 03 '13 at 10:07
  • I assumed it was some sort of collection, you assumed it was an array. My assumption was less concrete than yours. :) @CorbinSpicer, I am glad you got it working. – Sam Leach Oct 03 '13 at 10:38
0

Consider a Dictionary Object instead of an array if the data is conceptually one row multiple columns.

foreach(KeyValuePair<string, string> entry in MyDic)
{
    // do something with entry.Value or entry.Key
}
Brian Ogden
  • 18,439
  • 10
  • 97
  • 176
0

You already have a list of objects in fpts, sort that list itself:

fpts.OrderBy(x => x.Subject).ThenBy(x => x.Location).ToList();
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
0

LINQ is your friend here.

fapts appears to already be a collection so you could just operate on it.

var myNewArray = fapts.OrderBy(Appoint => Appoint.Start).ToArray()

I've used the ToArray() call to force immediate evaluation and means that myNewArray is already sorted so that if you use it more than once you don't have to re-evaluate the sort.

Alternatively if you are only using this once you can just as easily miss the ToArray() portion out and then execution of the sort will be deferred until you try and enumerate through myNewArray.

This solution puts the source objects into the array, but if you are just wanting to store the specific fields you mention then you will need to use a select. You have two choices for the array item type, you can either use an anonymous class which provides difficulties if you are returning this array from a function or define a class.

For anonymous:

 var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
                       .Select(Appoint => new {
                                Start = Appoint.Start,
                                Organiser = Appoint.Organiser.Name.ToString(),
                                Location = Appoint.Location 
                               }).ToArray();

For named class assuming class is MyClass:

 var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
                       .Select(Appoint => new MyClass {
                                Start = Appoint.Start,
                                Organiser = Appoint.Organiser.Name.ToString(),
                                Location = Appoint.Location 
                               }).ToArray();
Richard Ev
  • 52,939
  • 59
  • 191
  • 278
Bob Vale
  • 18,094
  • 1
  • 42
  • 49
-1

You have a wide range of options. The 2 most common are:

1) Create a class, then define an array or list of that class, and populate that

2) Create a structure that matches the data format and create an array or list of that

Of course, you could put the data into an XML format or dataset, but that's probably more work than you need.

public List<foo> appointments = new List<foo>(); 
public struct foo
{
public string subject ;
public DateTime start ;
public string name ;
public string location ;
}
public void foo1()
{
// parse the file
while (!File.eof())
    {
        // Read the next line...
        var myRecord = new foo() ;
        myRecord.subject = data.subject ;
        myRecord.start = data.Start ;
        myRecord.name = data.Name ;
        //...
        appointments.Add(myRecord);
    }
}

Enjoy

(Since I can't comment and reply to the comment - it wasn't clear if he had a class, etc. or was just showing us what he wanted to do. I assumed it was just for demonstration purposes since there wasn't any info as to how the data was being read. If he could already put it into a class, than the first answer applied anyway. I just tossed the last 2 in there because they were options for getting the data first.)

JustMeToo
  • 325
  • 1
  • 14