How to group a list of objects and after the grouping, get the list of objects that have the lowest value in c#?

Asked

Viewed 518 times

1

I have the following structure :

namespace teste
{
    public class Produto
    {

        public string Nome { get; set; }
        public decimal Valor { get; set; }

    }

    public class Program
    {

        public static void Main(string[] args)
        {
            var listaDeProdutos = new List<Produto>();

            var obj1 = new Produto
            {
                Nome = "celular",
                Valor = 10
            };

            var obj2 = new Produto
            {
                Nome = "celular",
                Valor = 15
            };

            var obj3 = new Produto
            {
                Nome = "teclado",
                Valor = 20
            };

            var obj4 = new Produto
            {
                Nome = "teclado",
                Valor = 30
            };

            var obj5 = new Produto
            {
                Nome = "monitor",
                Valor = 15
            };

            listaDeProdutos.Add(obj1);
            listaDeProdutos.Add(obj2);
            listaDeProdutos.Add(obj3);
            listaDeProdutos.Add(obj4);
            listaDeProdutos.Add(obj5);

        }
    }
}

I wonder how from mine listaDeProdutos get a new product list with the following rules:

1- The new list cannot have a repeated name product.

2- The new list should contain only minor products.

Expected result:

New products must have the following objects:

[0] Name = "cellular", Value = 10

[1] Name = "keyboard", Value = 20

[2] Name = "monitor", Value = 15

2 answers

2


With LINQ it’s that simple:

var novaLista = listaDeProdutos.OrderBy(o => o.Valor).GroupBy(x => x.Nome)
    .Select(x => x.First()).ToList();

See the example working in your code.

Basically what the code does is:

  1. Sort by value in ascending order.
  2. Group by product names.
  3. Select the first value of each group.
  4. Return to new list

1

Another option would be to implement the interface IEqualityComparer<T> and use the extension Distinct():

public class Produto : IEqualityComparer<Produto>
{
    public string Nome { get; set; }
    public decimal Valor { get; set; }

    public bool Equals(Produto x, Produto y)
    {
        return x.Nome.Equals(y.Nome);
    }

    public int GetHashCode(Produto obj)
    {
        return obj.Nome.GetHashCode();
    }        
}

To use:

var novaListaDeProdutos = listaDeProdutos.OrderBy(x => x.Valor).Distinct(new Produto()).ToList();

See working on dotnetfiddle

  • +1 Very good! Just one observation in this case: the comparison will always be true if the names are equal. And it may not always be the expected behavior.

Browser other questions tagged

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