Reputation: 916
I'm working with a third part service of my client that is providing me a list of products and services, which is a little bit of a mess.
The list will return all of the services
for the product
but the product
repeats itself
, for example:
The product A has the service A and the product A also has the service B so, when i receive the list i will get two products A with services A and B
What i need to do is to group all of the products to get only one with all of it's services and i have done so but i'm worried about performance because i think my solution isn't the 'best' one:
var productsNormalized = products.Data.AsEnumerable().Select(x => new ProdutoSSO
{
CodigoServico = int.Parse(string.IsNullOrEmpty(x["CodigoServico"].ToString()) ? "0" : x["CodigoServico"].ToString()),
CodigoPeca = int.Parse(string.IsNullOrEmpty(x["CodigoPeca"].ToString()) ? "0" : x["CodigoPeca"].ToString()),
CodigoFamilia = int.Parse(string.IsNullOrEmpty(x["CodigoFamilia"].ToString()) ? "0" : x["CodigoFamilia"].ToString()),
Familia = x["Familia"].ToString(),
Servico = x["Servico"].ToString(),
Peca = x["Peca"].ToString(),
Hash = x["Hash"].ToString(),
Valor = decimal.Parse(string.IsNullOrEmpty(x["Valor"].ToString()) ? "0" : x["Valor"].ToString())
})
.GroupBy(x => new { x.CodigoPeca, x.CodigoFamilia, x.Familia, x.Peca })
.Select(x => new ProdutoGroup
{
Produto = new Produto
{
CodigoPeca = x.Key.CodigoPeca,
CodigoFamilia = x.Key.CodigoFamilia,
Familia = x.Key.Familia,
Peca = x.Key.Peca
},
Servicos = x.Select(y => new ProdutoServico
{
CodigoServico = y.CodigoServico,
Hash = y.Hash,
Servico = y.Servico,
Valor = y.Valor
}).ToList()
});
Is there a better way to achieve this or this is as good as it gets?
Upvotes: 0
Views: 1635
Reputation: 45135
Using Aggregate you could do something like this (assuming you are starting with a list of ProdutoSSO
, which might not be entirely necessary):
var productsNormalized = productoSSOs
.Aggregate(new Dictionary<Produto,List<ProdutoServico>>(ProductoComparer),
(p,c) => {
var product = new Produto
{
CodigoPeca = c.CodigoPeca,
CodigoFamilia = c.CodigoFamilia,
Familia = c.Familia,
Peca = c.Peca
};
var service = new ProdutoServico
{
CodigoServico = c.CodigoServico,
Hash = c.Hash,
Servico = c.Servico,
Valor = c.Valor
};
if (!p.ContainsKey(product))
{
p[product] = new List<ProductoServico>() { service };
}
else
{
p[product].Add(service);
}
return p;
});
Where ProductoComparer
is an IEqualityComparer<Producto>
(or alternatively you could implement Equals
and GetHashCode
in Producto
, or you could just generate a key some other way - concatenating fields together, for example).
This is obviously untested since I don't have the original classes or data.
This would give you a Dictionary<Producto, List<ProductoServico>>
which might be all you need, or you can easily transform it into an IEnumerable<ProdutoGroup>
if you want.
Upvotes: 2