2017-07-07 57 views
1

我正在为客户提供第三方服务,该服务向我提供产品和服务的清单,这些清单有点乱。C#Linq GroupBy和Select性能

名单将返回所有servicesproductproductrepeats itself,例如:

产品A服务A产品A也有服务B所以,当我收到名单我会得到两个产品A服务A和B

我需要做的是将所有产品进行分组,以获得所有产品的服务,并且我已经这样做了,但是我担心性能,因为我认为我的解决方案不是'最好的':

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() 
}); 

有没有更好的方法来实现这一目标,或者这样做还不错?

+4

代码需要多长时间?你想要多久? – mjwills

+1

*'只能得到一个所有的服务'* - 看起来好像你在查询所有组和所有服务。没有过滤,也没有像'Take(1)'或'First()'# –

+0

@SergeyBerezovskiy问题是服务,它将返回一个所有产品的列表,没有过滤器,没有任何东西。我必须在我身边这样做 – Terkhos

回答

2

使用聚合,你可以做这样的事情(假设你开始用ProdutoSSO名单,这可能不是完全必要的):

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; 
}); 

ProductoComparerIEqualityComparer<Producto>(或者你也可以实现EqualsGetHashCodeProducto中,或者您可以通过其他方式生成密钥 - 例如将字段连接在一起)。

这显然没有经过测试,因为我没有原始的类或数据。

这会给你一个Dictionary<Producto, List<ProductoServico>>这可能是你所需要的,或者你可以很容易地将它转换成IEnumerable<ProdutoGroup>如果你想。

+0

它给我一个错误:'的类型参数方法 'Enumerable.Aggregate (IEnumerable的,TAccumulate,函数功能)' 不能从使用推断。尝试明确指定类型参数' – Terkhos

+0

对不起,我*总是*在使用'Aggregate'时忘记'return'。现在就试试。 –

+0

我已经添加了返回p。它仍然向我显示相同的消息,看起来它不能定义类型。我试图在'Aggregate <>'中添加它们,但我找不到正确的匹配项。 – Terkhos