Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove all items from a List<T> if variations of T occur

been struggling with this for a while now.

I'm dipping my toe in the WebAPI world and I have a List that can contains products with the same name but different prices. What I need to do is remove all references to a product is variations in price occur.

eg.
name = "Cornflakes" Price = "1.99M"
name = "Cornflakes" Price = "1.89M"
name = "Rice Krispies" Price = "2.09M"
name = "Cornflakes" Price = "2.09M"

No cornflakes should appear in my final list.

I've got the bulk written but it's removing the products too soon and I'm unsure where I should be removing them.

public IEnumerable<Product> GetProductsByCategory(int Id)
    {
        List<Product> sourceProductList = products.Where(p => p.CategoryID == Id).ToList();
        List<Product> tempProducts = new List<Product>();
        List<Product> targetProductList = new List<Product>();

        foreach (var product in sourceProductList)
        {
            bool isInTempList = tempProducts.Any(x => x.Name == product.Name);
            if (!isInTempList)
            {
                tempProducts.Add(product);
            }
            else
            {
                Product tempProduct = product;
                bool isPriceDifferent = tempProducts.Where(y => y.Name == tempProduct.Name).Any(y => y.Price != tempProduct.Price);
                if (isPriceDifferent)
                {
                    tempProducts.RemoveAll(p => p.Name == product.Name); 
                    // too soon as I may have lots of products with the same name
                    // but need to remove based on product.Name
                }
            }
        }
        targetProductList.AddRange(tempProducts);

        return targetProductList;
    }

Any help would be greatly appreciated.

Note: other cereals are available

like image 927
Brett Avatar asked Oct 11 '12 13:10

Brett


People also ask

Does list remove remove all occurrences?

The remove() Method Removes the First Occurrence of an Item in a List. A thing to keep in mind when using the remove() method is that it will search for and will remove only the first instance of an item.

Does remove in Python remove all occurrences?

In Python remove() will remove the first occurrence of value in a list.

Which method removes all the items from the list?

The clear() method will remove all the elements present in the list.


3 Answers

Try this LINQ expression that will only select the products that have one distinct price:

var result = sourceProductList
    .GroupBy(x => x.Name)
    .Where(g => g.Select(x => x.Price).Distinct().Count() == 1)
    .Select(g => g.First());

See it working online: ideone.

like image 75
Mark Byers Avatar answered Oct 18 '22 04:10

Mark Byers


Please try this:

class Program
    {
        static void Main(string[] args)
        {
            var list = new List<Product>
                {
                    new Product() {Name = "Cornflakes", Price = 100},
                    new Product() {Name = "Cornflakes", Price = 200},
                    new Product() {Name = "Rice Krispies", Price = 300},
                    new Product() {Name = "Cornflakes", Price = 400}
                };

            var uniqueItems = list.Where(w => (!list.Any(l=>l.Name.Equals(w.Name) && l != w)));

        }

        public class Product
        {

            public string Name { get; set; }
            public decimal Price { get; set; }
        }
    }

In the result you will have only one "Rice Krispies" item. I'm sure it will work faster than solution with GroupBy and Distinct, because we don't need to do these unnecessary things in your case.

Working Code - http://ideone.com/X8A3v

like image 32
Sergey Avatar answered Oct 18 '22 04:10

Sergey


Something like this (freehand so may be slightly wrong syntax):

var toRemove = sourceProductList
    .GroupBy(p => p.Name)
    .Where(g => g.Count() > 1)
    .SelectMany(g => g)
    .GroupBy(p => p.Price)
    .Where(g => g.Count() > 1)
    .SelectMany(g => g.Select(p => p.ID))
    .Distinct()
    .ToList();
toRemove.ForEach(id => sourceProductList.RemoveAll(p => p.ID == id));
like image 1
Paul Fleming Avatar answered Oct 18 '22 04:10

Paul Fleming