简体   繁体   中英

Filter a list of objects

I have a list of objects in an ArrayList PList . The object looks like this

Product 
{
    int ProductId,
    string ProductDescription,
    int StoreId 
    int supplierid
}

I would like to add non repeating combination of Products into another array

Product[] Parray

example:

ArrayList Plist has :

productid , productdescription, storeid, supplierid

1, "AB", 11 , 123
2, "CD", 24 ,454
1, "AB", 11 ,431

I would like the Product[] Parray to have

productid , productdescription, storeid, supplierid
1, "AB", 11 ,123
2, "CD", 24 , 454

I know that I can use a hashtable for key value pairs ,but in this case I have 3 keys ProductId, description & storeid

Here is my code as of now:

private Types.Product[] LoadProducts()
{
    ArrayList PList = new ArrayList(); 
    // Business Logic , extracting values from xml using xpath
    //Loop though each xml node
    for (int j = 0; j < xmlprodlist.Count; j++)
    {
        //Business logic
        PList.Add(call another function here);
    }
    //What code here ??
    Types.Product[] PArray = (Types.Product[])PArrayList.ToArray(typeof(Types.Product));   
    return PArray;
}

Can anyone tell me what code I need to add above in the place what code here ?

You could use a simple GroupBy to group your data, and select the first item of each group:

Product[] Parray = PList.OfType<Product>()
                        .GroupBy(p => new {p.ProductId, p.ProductDescription, p.StoreId})
                        .Select(p => p.First())
                        .ToArray();

Note that you don't have a reason to use ArrayList anymore (you even tagged your question C# 4.0), better use the generic List<T> class, which will make your code more typesafe and more understandable.

Another way is to provide a IEqualityComparer that compares the three properties in question to the Distinct method:

Product[] Parray = PList.OfType<Product>()
                        .Distinct(theIEqualityComparer)
                        .ToArray();

I probably did not understand... why not an hastable int->Product (productId->Product)

something like (sorry I don't have ac# compiler here, this is just a draft)

proDictionary<int, Product> table = new Dictionary<int, Product>();

foreach (var x : inproducts)
     // if (!table.Keys.Contains(x)) // if you want to keep the first
    table.Add(x.ProductId, x);

return table.Values.ToArray();

From what i understand you have a list of products and you want a distict list based on the ID. First override Equals and GetHashCode in the Product class and then use LINQ to get the distict items:

public class Product
{
    public int ProductId;
    public string ProductDescription;
    public int StoreId;
    public int supplierid;


    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
            return false;

        return ProductId == ((Product)obj).ProductId;
    }


    public override int GetHashCode()
    {
        return ProductId.GetHashCode();
    }
}

And use it like this

List<Product> products = new List<Product>();
products.Add(new Product() { ProductId = 1, ProductDescription = "Product 1" });
products.Add(new Product() { ProductId = 2, ProductDescription = "Product 2" });
products.Add(new Product() { ProductId = 3, ProductDescription = "Product 3" });
products.Add(new Product() { ProductId = 1, ProductDescription = "Product 1 again" });

var distictItems = products.Distinct().ToList();
Console.WriteLine(distictItems.Count()); //This prints 3

One way to do this would be to write an implementation of IEqualityComparer. Something like:

public class ProductEqualityComparer : IEqualityComparer<Product>
{
    public bool Equals(Product x, Product y)
    {
        return x != null && y != null &&
               x.ProductId == y.ProductId &&
               x.ProductDescription == y.ProductDescription &&
               x.StoreId == y.StoreId;
    }

    public int GetHashCode(Product obj)
    {
        return String.Format("{0}-{1}-{2}",
            obj.ProductId,
            obj.ProductDescription,
            obj.StoreId)
            .GetHashCode();
    }
}

You could then do:

var comparer = new ProductEqualityComparer();
var array = (Types.Product[])PList.ToArray(typeof(Types.Product));
var distinct = array.Distinct(comparer);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM