# Group a list of products and services

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?

• If it's working correctly, and working for acceptable time, then you don't have reasons to change it. – tym32167 Jul 7 '17 at 16:13
• @tym32167 i can't fully test it for now because i don't have the full database. But as i was told we are going to work with something close to 3k requests per day and 400 products. – Terkhos Jul 10 '17 at 14:08

There are some improvemants possible but they are rather of technical nature then about performance as I don't think you can do much about it until you have measured it either with benchmarks or a profiler.

products.Data.AsEnumerable()


This looks like you are working with a DataTable, aren't you? If the data comes from a database then you should group it on the server.

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()),


You should create a helper extension or function for such lines, it's pretty ugly to repeat it so many times. Even two times is already too many.

.GroupBy(x => new { x.CodigoPeca, x.CodigoFamilia, x.Familia, x.Peca })


You are grouping by the same properties as the object has that you create in the next step:

Produto = new Produto
{
CodigoPeca = x.Key.CodigoPeca,
CodigoFamilia = x.Key.CodigoFamilia,
Familia = x.Key.Familia,
Peca = x.Key.Peca
},


Instead of doing this twice you should implement the IEquatable<Produto> interface on this object and use this instance as a key so that you only have a single new.

Servicos = x.Select(y => new ProdutoServico
{
CodigoServico = y.CodigoServico,
Hash = y.Hash,
Servico = y.Servico,
Valor = y.Valor
}


You can replace this with Servicos = x if you use another overload of GroupBy and project each item right away.

• I have managed to implement most of your tips but i couldn't find my way to implement the IEquatable and how to use it on the Select. Could you please provide a small example with the GroupBy overload ? I'm quite new to C#. Thanks. – Terkhos Jul 10 '17 at 14:03
• @Terkhos I completely forgot your question about the IEquatable, sorry ;-] I'll answer with a link because I think this a nice explanation how to do it correctly. – t3chb0t Jul 25 '17 at 14:44