"Filter" equal records into a list by adding their quantitative

Asked

Viewed 2,109 times

5

namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Teste> lstTeste = new List<Teste>
            {
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10},
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 3, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10}
            };
        }
    }

    public class Teste
    {
        public int Codigo { get; set; }
        public int Quantidade { get; set; }
    }

I want to create a new list, or remove the repeated items from the original list, but I want to add the quantitative.

The "new" list would be:

Codigo = 1, Quantitativo = 20
Codigo = 2, Quantitativo = 20
Codigo = 3, Quantitativo = 10

4 answers

6


Using LINQ you can group the items by code and add the amount in each group. However, LINQ is only available from version 3.5 and in some cases we need to work with previous versions, so I also made a solution grouping and summing using a Dictionary as a key/value structure for grouping items by code and adding quantities directly to the item value in the dictionary.

With LINQ

namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Teste> lstTeste = new List<Teste>
            {
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10},
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 3, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10}
            };

            List<Teste> lstAgrupado = lstTeste
                .GroupBy(i => i.Codigo)
                .Select(j => new Teste()
                {
                    Codigo = j.First().Codigo,
                    Quantidade = j.Sum(ij => ij.Quantidade)
                })
                .ToList();
        }
    }

    public class Teste
    {
        public int Codigo { get; set; }
        public int Quantidade { get; set; }
    }
}

Linless

namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Teste> lstTeste = new List<Teste>
            {
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10},
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 3, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10}
            };

            Dictionary<int, Teste> agrupamentoSomado = new Dictionary<int, Teste>();

            foreach (Teste item in lstTeste)
            {
                if (agrupamentoSomado.ContainsKey(item.Codigo))
                {
                    agrupamentoSomado[item.Codigo].Quantidade += item.Quantidade;
                }
                else
                {
                    agrupamentoSomado.Add(item.Codigo, item);
                }
            }

            List<Teste> lstAgrupado = new List<Teste>(agrupamentoSomado.Values);
        }
    }

    public class Teste
    {
        public int Codigo { get; set; }
        public int Quantidade { get; set; }
    }
}

3

I made it in three different ways to choose the one that suits you best:

using System.Collections.Generic;
using System.Linq;
using static System.Console;

namespace ConsoleApplication10 {
    public class Program {
        public static void Main(string[] args) {
            List<Teste> lstTeste = new List<Teste> {
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10},
                new Teste {Codigo = 1, Quantidade = 10},
                new Teste {Codigo = 3, Quantidade = 10},
                new Teste {Codigo = 2, Quantidade = 10}
            };

            //Forma declarativa
            WriteLine("Forma declarativa");
            var items = from item in lstTeste
                group item by item.Codigo
                into g
                select new{Codigo = g.Key, Quantidade = g.Sum(item => item.Quantidade)};
            items.ToList().ForEach(item => { WriteLine(
                $"Item: {item.Codigo} Quantidade: {item.Quantidade}"); });

            //forma imperativa
            WriteLine("Forma imperativa");
            var lista = lstTeste.GroupBy(g => g.Codigo).Select(g => new {
                Codigo = g.First().Codigo, Quantidade = g.Sum(g => g.Quantidade) });
            lista.ToList().ForEach(item => { WriteLine(
                $"Item: {item.Codigo} Quantidade: {item.Quantidade}"); });

            //forma com dicionário - Sem LINQ
            WriteLine("Forma com dicionário");
            var dicionario = new Dictionary<int, Teste>();
            foreach (var item in lstTeste) {
                if (dicionario.ContainsKey(item.Codigo)) {
                    dicionario[item.Codigo].Quantidade += item.Quantidade;
                } else {
                    dicionario[item.Codigo] = item;
                }
            }
            foreach (var item in dicionario.Values) {
                WriteLine($"Item: {item.Codigo} Quantidade: {item.Quantidade}");
            }
       }
    }

    public class Teste {
        public int Codigo { get; set; }
        public int Quantidade { get; set; }
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

3

A response using the extension methods of System.Linq and return with anonymous objects:

var resultado = lstTeste
      .GroupBy(x => x.Codigo)
      .Select(x => new { 
          Quantitativo = x.Sum(y => y.Quantidade), 
          Codigo = x.First().Codigo
      });

See working here: https://dotnetfiddle.net/S1FKzY

1

public static List<Teste> SomarIguais(List<Teste> list)
{
    if(list == null) return null;
    List<Teste> resultado = new List<Teste>();
    foreach(Teste t in list)
    {
        bool nenhum = true;
        foreach(Teste t1 in resultado)
        {
            if(t1.Codigo == t.Codigo)
            {
                nenhum = false;
                t1.Quantidade += t.Quantidade;
            }
        }
        if(nenhum) resultado.Add(t);
    }
    return resultado;
}
  • Christian, try to explain a little of the logic you adopted when posting a reply. And if you don’t have LINQ available I suggest using Dictionary ;)

  • I honestly had never used Linq. How much logic seemed so "silly" that I didn’t even find it necessary

  • 1

    It’s a matter of good practice, Christian. What may be trivial to you may not be trivial to other people. To whoever asked the question,.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.