2

Hey guys - I'm stuck with this problem and im just wondering what the best way to handle it is.

Foreach (var customer in CustomerList)
{
      Foreach (var appointment in AppointmentList)
      {
        if(appointment.customerId == customer.id)
           customer.appointments.add(appointment)


       }

}

this is the simplest way I can think to do it but im not sure if it's the most efficient!

Any help would be great-

Thanks.

4 Answers 4

2

You could perhaps pre-group the shorter list; this should give you better performance - I can't find citations to the exact big-O ratings since MSDN doesn't cite them, but it could be O(n + m) instead of O(n * m).

var apptsByCustomer = AppointmentList.ToLookup(appt => appt.customerId);

then you can use:

foreach (var customer in CustomerList) {
    foreach(var appointment in apptsByCustomer[customer.id]) {
        customer.appointments.add(appointment);
    }
}

Or without LINQ (from comments):

// this bit is **broadly** comparable to ToLookup...
Dictionary<int, List<Appointment>> apptsByCustomer =
     new Dictionary<int, List<Appointment>>();
List<Appointment> byCust;
foreach(Appointment appt in AppointmentList) {            
    if (!apptsByCustomer.TryGetValue(appt.customerId, out byCust)) {
        byCust = new List<Appointment>();
        apptsByCustomer.Add(appt.customerId, byCust);
    }
    byCust.Add(appt);
}

foreach (Customer cust in CustomerList) {
    if (apptsByCustomer.TryGetValue(cust.id, out byCust)) {
        foreach (Appointment appt in byCust) cust.appointments.Add(appt);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Does that compile? I thought IGrouping has no indexer? Did you want to use ToLookup? If you use ToLookup it should be (almost) O(n+m)
@CodeInChaos - d'oh! I did indeed mean ToLookup
@Stephen - adding a non-LINQ version
Brilliant mate thanks. I think I could get away with linq extensions actually - the ToLookup to me looks far me readable that the non linq code.
2

What about this?

foreach (var customer in CustomerList)
{
    customer.AddRange( appointment.Where( a => a.CustomerId == customer.id));
}

For me this seems like a clear and concise syntax, and it explains what it does quite good.

Also, I think the performance should be fine here, and probably around the same as your original code.

Comments

0

You could use linq to remove nesting from loops, like this:

foreach (var customer in from customer in CustomerList
         from appointment in AppointmentList
         select customer)
{
    // ...
}

1 Comment

How does this add appointments to the customers appointment-list?
0

You could make your customerList a Dictionary instead consisting of <id, cust>.

Then, instead of looping the list you try to get the value

Dictionary<int, Customer> customerList = new Dictionary<int, Customer>();
// populate your list
// ...
foreach (var appointment in AppointmentList)
{
    Customer customer;
    if (customerList.TryGetValue(appointment.customerID, out customer)){
        // found the customer
        customer.appointments.add(appointment)
}

This way, you let Dictionary optimize it for you.
Do note that if you only perform this action once, it's probably not worth optimizing much unless you see a notable slowdown from it. Premature optimization is not really worth the effort

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.