MerJ
MerJ

Reputation: 3

Is there a way to increase performance on these two foreach loops?

I'm currently working on an application for customers to help update customer information. The Customers query returns minimum 500 results. The CustomerItemList is a separate item list. Both lists contain Customer PK. I need to merge these two lists where the customerPK matches. It's important to note that the customer pk can be listed more than once in the customer item list! The below code snippet works, but is very slow. I'm hoping to update it with linq, but I haven't found anything that increases performance yet.

Thanks for your help in advance!

            var Customers = LookupCustomers(CustomerItemList); //returns 500

            foreach (var customer in Customers)
            {
                var CustomerIDList = CustomerItemList.Where(x => x.CustomerPK.Equals(customer.CustomerPK)).ToList(); //returns at least 2 results
                foreach (var CustomerID in CustomerIDList)
                {
                    CustomerID.CustomerPrimaryCard = customer.PrimaryCardID + ", 1";
                }
            }

Upvotes: 0

Views: 132

Answers (3)

Aleks Andreev
Aleks Andreev

Reputation: 7054

Try convert your CustomerItemList into a dictionary:

var customersDict = CustomerItemList.GroupBy(c => c.CustomerPK)
    .ToDictionary(k => k.Key, v => v.ToList());

Then in foreach use this code:

foreach (var customer in Customers)
{
    List<CustomerItem> items; // not sure about elements type of CustomerItemList
    if (!customersDict.TryGetValue(customer.CustomerPK, out items))
        continue;

    foreach (var CustomerID in items)
        CustomerID.CustomerPrimaryCard = customer.PrimaryCardID + ", 1";
}

Upvotes: 1

JuanR
JuanR

Reputation: 7783

You could try this:

Customers
    .Join(CustomerItemList, c => c.CustomerPK, i => i.CustomerPK, (c, i) => new { Customer = c, Item = i })
    .ToList()
    .ForEach(r => { r.Item.CustomerPrimaryCard = r.Customer.PrimaryCardID + ", 1"; });

Alternatively, you can try this:

Customers
    .Join(CustomerItemList, c => c.CustomerPK, i => i.CustomerPK, (c, i) => new { Customer = c, Item = i })
    .AsParallel()
    .ForAll(r => { r.Item.CustomerPrimaryCard = r.Customer.PrimaryCardID + ", 1"; });

But parallel processing is best used if you have a large number of results and/or resource-intensive operations. Otherwise, it will actually be slower.

The general idea is to use Set operations.

Upvotes: 1

Michael
Michael

Reputation: 2113

If your CustomerItemList is large, pre-sort it by your search critera CustomerPK and use BinarySearch to retrieve the first occurence of the searched item. Start iterating from there and break with the first non-matching CustomerPK

Upvotes: 0

Related Questions