Reputation: 31
I have two lists different types. The first list is type of below class:
public partial class PersonOneProductOne
{
public int PersonOneId { get; set; }
public int ProductOneId { get; set; }
}
The second list is type of below class:
public partial class PersonTwoProductTwo
{
public int PersonTwoId { get; set; }
public int ProductTwoId { get; set; }
}
I want to add to list type of PersonOneProductOne missing objects from list type of PersonTwoProductTwo but unfortunatelly it isn't so easy because I have also lists how to map PersonOneId and ProductOneId from PersonOneProductOne class to PersonTwoId and ProductTwoId in PersonTwoProductTwo class:
public class PersonOnePersonTwo
{
public int PersonOneId { get; set; }
public int PersonTwoId { get; set; }
}
public class ProductOneProductTwo
{
public int ProductOneId { get; set; }
public int ProductTwoId { get; set; }
}
I have written below code but it is slow, is better way??
// data:
List<PersonOneProductOne> personOneProductOneList = new List<PersonOneProductOne>();
List<PersonTwoProductTwo> personTwoProductTwoList = new List<PersonTwoProductTwo>();
// how to map:
List<PersonOnePersonTwo> personOnePersonTwoMapping = new List<PersonOnePersonTwo>();
List<ProductOneProductTwo> productOneProductTwoMapping = new List<ProductOneProductTwo>();
// my algorithm which is slow:
foreach (PersonTwoProductTwo personTwoProductTwo in personTwoProductTwoList)
{
PersonOnePersonTwo personOnePersonTwo = personOnePersonTwoMapping.FirstOrDefault(x => x.PersonTwoId == personTwoProductTwo.PersonTwoId);
ProductOneProductTwo productOneProductTwo = productOneProductTwoMapping.FirstOrDefault(x => x.ProductTwoId == personTwoProductTwo.ProductTwoId);
if (personOnePersonTwo != null && productOneProductTwo != null)
{
PersonOneProductOne personOneProductOne = personOneProductOneList.FirstOrDefault(x => x.PersonOneId == personOnePersonTwo.PersonOneId && x.ProductOneId == productOneProductTwo.ProductOneId);
if (personOneProductOne == null)
{
personOneProductOneList.Add(new PersonOneProductOne
{
PersonOneId = personOnePersonTwo.PersonOneId,
ProductOneId = productOneProductTwo.ProductOneId
});
}
}
}
Upvotes: 0
Views: 40
Reputation: 13224
The code fragment below is not going to speed up your query. It is a translation of your current logic into a single LINQ query. I included it, because it makes your current logic a lot easier to follow (i.e. it is more readable), which is always a good starting point when attempting an optimization.
var result =
from person2product2 in personTwoProductTwoList
from person1person2 in personOnePersonTwoMapping
from product1product2 in productOneProductTwoMapping
where person2product2.PersonTwoId == person1person2.PersonTwoId &&
person2product2.ProductTwoId == product1product2.ProductTwoId &&
!personOneProductOneList.Any(x =>
x.PersonOneId == person1person2.PersonOneId &&
x.ProductOneId == product1product2.ProductOneId)
select new PersonOneProductOne {
PersonOneId = person1person2.PersonOneId,
ProductOneId = product1product2.ProductOneId
};
personOneProductOneList.AddRange(result);
An obvious thing that could be optimized, is to use use dictionaries with O(1) lookup time instead of your "mapping" lists, that will have O(N) lookup time.
When using dictionaries and assuming each person id and product id has an entry, this could then be transformed into:
// Maps PersonTwoId (key) to PersonOneId (value)
Dictionary<int, int> personTwoPersonOneMapping;
// Maps ProductTwoId (key) to ProductOneId (value)
Dictionary<int, int> productTwoProductOneMapping;
var result =
from person2product2 in personTwoProductTwoList
where !personOneProductOneList.Any(x =>
x.PersonOneId == personTwoPersonOneMapping[person2product2.PersonTwoId] &&
x.ProductOneId == productTwoProductOneMapping[person2product2.ProductTwoId])
select new PersonOneProductOne {
PersonOneId = personTwoPersonOneMapping[person2product2.PersonTwoId],
ProductOneId = productTwoProductOneMapping[person2product2.ProductTwoId]
};
Upvotes: 1