リスト/ネストリストの問題から重複アイテムを削除するという古典的な問題があります。ただし、私が従おうとしている特定のルールのため、解決策は単純ではありません。希望どおりに動作するサンプルアプリケーションを作成しました。しかし、それは不格好なようです。私はより優雅で、可能であればより効率的なものを探しています。たぶん、LINQ/拡張メソッドが役立つかもしれません。助言がありますか?
class Program
{
static void Main(string[] args)
{
var sellers = new List<Seller>()
{
new Seller()
{
Id = 1,
Products = new List<Product>()
{
new Product() { Sku = "Alpha", Price = 5.0, Shipping = 2.0 },
new Product() { Sku = "Beta", Price = 5.0, Shipping = 2.0 }, // more expensive sku within same seller
new Product() { Sku = "Beta", Price = 4.0, Shipping = 2.0 },
new Product() { Sku = "Gamma", Price = 8.0, Shipping = 2.0 }
}
},
new Seller()
{
Id = 2,
Products = new List<Product>()
{
new Product() { Sku = "Alpha", Price = 5.0, Shipping = 1.0 },
new Product() { Sku = "Beta", Price = 5.0, Shipping = 1.0 },
new Product() { Sku = "Gamma", Price = 8.0, Shipping = 2.0 }
}
}
};
// Eliminate duplicate Products amongst all sellers that have matching "Sku".
// Rules:
// Keep the Product with the lowest price.
// If price is equal, keep the product with lower shipping.
// If shipping is also equal, then keep the product with lowest seller Id.
// If at the end of all comparisons, a seller ends up with no products, then remove that seller.
// In this example, I expect to have (not necessarily in this order):
// 1.{Beta, 4.0, 2.0} // Fred.Beta has a lower price than Bob.Beta
// 1.{Gamma, 8.0, 2.0} // Fred.Gamma is an identical deal to Bob, but Fred is first in the list
// 2.{Alpha, 5.0, 1.0} // Bob.Alpha has a lower shipping cost than Fred.Alpha
var newSellers = new List<Seller>();
foreach (var seller in sellers)
{
foreach (var product in seller.Products)
{
// TODO: Possible performance improvement? Check for existing seller & product in newSellers before calling any code below.
var bestSeller = seller;
var bestProduct = product;
FindBestSellerAndProduct(sellers, ref bestSeller, ref bestProduct);
AddIfNotExists(newSellers, bestSeller, bestProduct);
}
}
newSellers.Sort((x, y) => x.Id.CompareTo(y.Id)); // Ensures the list is sorted by seller id... do I really care?
}
private static void FindBestSellerAndProduct(IList<Seller> sellers, ref Seller seller, ref Product product)
{
string sku = product.Sku;
foreach (var s in sellers)
{
foreach (var p in s.Products.Where(x => x.Sku == sku))
{
if ((product.Price > p.Price) ||
(product.Price == p.Price && product.Shipping > p.Shipping) ||
(product.Price == p.Price && product.Shipping == p.Shipping && seller.Id > s.Id))
{
seller = s;
product = p;
}
}
}
}
private static void AddIfNotExists(IList<Seller> sellers, Seller seller, Product product)
{
var newSeller = sellers.SingleOrDefault(x => x.Id == seller.Id);
if (newSeller == null)
{
// Add input seller and product if seller doesn't already exist in our list.
newSeller = new Seller() { Id = seller.Id, Products = new List<Product>() };
newSeller.Products.Add(product);
sellers.Add(newSeller);
}
else
{
var newProduct = newSeller.Products.Find(x => x.Sku == product.Sku);
if (newProduct == null)
{
// Add input product if it doesn't already exist in our list
newSeller.Products.Add(product);
}
}
}
}
// I cannot modify the below classes.
public sealed class Seller
{
public int Id;
public List<Product> Products;
}
public sealed class Product
{
public string Sku;
public double Price;
public double Shipping;
}