Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two large generic lists

Tags:

c#

.net-4.0

I cannot find a specific example of this, so am posting the question. Any help appreciated.

I have two large generic lists, both with over 300K items.

I am looping through the first list to pull back information and generate a new item for a new list on the fly, but I need to search within the second list and return a value, based on THREE matching criteria, if found to add to the list, however as you can imagine, doing this 300k * 300k times is taking time.

Is there any way I can do this more efficiently?

My code:

var reportList = new List<StocksHeldInCustody>();
foreach (var correctDepotHolding in correctDepotHoldings)
  {
    var reportLine = new StocksHeldInCustody();
    reportLine.ClientNo = correctDepotHolding.ClientNo;
    reportLine.Value = correctDepotHolding.ValueOfStock;
    reportLine.Depot = correctDepotHolding.Depot;
    reportLine.SEDOL = correctDepotHolding.StockCode;
    reportLine.Units = correctDepotHolding.QuantityHeld;
    reportLine.Custodian = "Unknown";
    reportLine.StockName = correctDepotHolding.StockR1.Trim() + " " + correctDepotHolding.StockR2.Trim();

    //Get custodian info

    foreach (var ccHolding in ccHoldList)
    {
      if (correctDepotHolding.ClientNo != ccHolding.ClientNo) continue;
      if (correctDepotHolding.Depot != ccHolding.Depot) continue;
      if (correctDepotHolding.StockCode != ccHolding.StockCode) continue;
      if (correctDepotHolding.QuantityHeld != ccHolding.QuantityHeld) continue;
      reportLine.Custodian = ccHolding.Custodian;
      break;
    }
    reportList.Add(reportLine);
  }
like image 281
David Johnson Avatar asked Aug 15 '12 09:08

David Johnson


3 Answers

As Pranay says, a join is probably what you want:

var query = from correct in correctDepotHoldings
            join ccHolding in ccHoldList
              on new { correct.ClientNo, correct.Depot,
                       correct.StockCode, correct.QuantityHeld }
              equals new { ccHolding.ClientNo, ccHolding.Depot,
                           ccHolding.StockCode, ccHolding.QuantityHeld }
            // TODO: Fill in the properties here based on correct and ccHolding
            select new StocksHeldInCustody { ... };
var reportList = query.ToList();
like image 115
Jon Skeet Avatar answered Oct 31 '22 20:10

Jon Skeet


You could move the data from the lookup list into a dictionary, with the key being a unique hash of the 3 items you are searching on. Then you will have very quick lookups and save millions of iterations.

like image 3
cjk Avatar answered Oct 31 '22 20:10

cjk


Check my full post : Linq Join on Mutiple columns using Anonymous type

Make use of Linq inner join that will do work for you.

var list =  ( from x in entity
           join y in entity2 
          on new { x.field1, x.field2 } 
        equals new { y.field1, y.field2 }
        select new entity { fields to select}).ToList();

Join of linq on multiple field

enter image description here

EmployeeDataContext edb= new EmployeeDataContext();
var cust = from c in edb.Customers
           join d in edb.Distributors on
             new { CityID = c.CityId, StateID = c.StateId, CountryID = c.CountryId,
                   Id = c.DistributorId }   
           equals
             new { CityID = d.CityId, StateID = d.StateId, CountryID = d.CountryId,
                   Id = d.DistributorId }   
           select c;
like image 3
Pranay Rana Avatar answered Oct 31 '22 21:10

Pranay Rana