I have a collection of Products in a list (List<Product>
) where product holds id, name and price.
If I would order the list in a descending way based on price, is there a one liner or extensionmethod that allows me to insert a new product in the correct position of the list?
public class Product
{
public int Id {get; set;}
public string Name {get; set;}
public int Price {get; set;} // assume only whole integers for price
}
public class Main()
{
List<Product> products = new();
products.Add(new Product(id= 1, Name="Product1", Price=10 };
products.Add(new Product(id= 2, Name="Product2", Price=15 };
products.Add(new Product(id= 3, Name="Product3", Price=11 };
products.Add(new Product(id= 4, Name="Product4", Price=20 };
products = products.OrderByDescending(prd => prd.Price).ToList();
var newProduct = new({id = 5, Name="new product", Price = 17})
// Is there an short solution available that allows me to insert a new product with
// price = 17 and that will be inserted between products with price 15 and 20?
// Without repeatedly iterating over the list to find the one lower and the one higher
// than the new price and recalculate the index...
var lastIndex = products.FindLastIndex(x => x.Price >= newProduct.Price);
products.Insert(lastIndex 1, p5);
}
CodePudding user response:
You can use a SortedList<TKey, TValue>
:
SortedList<int, Product> productList = new();
var p = new Product{ Id = 1, Name = "Product1", Price = 10 };
productList.Add(p.Price, p);
p = new Product { Id = 2, Name = "Product2", Price = 15 };
productList.Add(p.Price, p);
p = new Product { Id = 3, Name = "Product3", Price = 11 };
productList.Add(p.Price, p);
p = new Product { Id = 4, Name = "Product4", Price = 20 };
productList.Add(p.Price, p);
p = new Product { Id = 5, Name = "Product5", Price = 17 };
productList.Add(p.Price, p);
foreach(var x in productList)
Console.WriteLine($"{x.Key} {x.Value.Name}");
outputs:
10 Product1
11 Product3
15 Product2
17 Product5
20 Product4
Edit: Note that it doesn't allow duplicate keys, so like a dictionary. You could solve it by using a SortedList<int, List<Product>>
. For example with this extension method:
public static class CollectionExtensions
{
public static void AddItem<TKey, TValue>(this SortedList<TKey, List<TValue>> sortedList, TValue item, Func<TValue, TKey> getKey)
{
TKey key = getKey(item);
if (sortedList.TryGetValue(key, out var list))
{
list.Add(item);
}
else
{
sortedList.Add(key, new List<TValue> { item });
}
}
}
Usage:
SortedList<int, List<Product>> productLists = new();
productLists.AddItem(new Product { Id = 1, Name = "Product1", Price = 10 }, p => p.Price);
productLists.AddItem(new Product { Id = 2, Name = "Product2", Price = 10 }, p => p.Price);
productLists.AddItem(new Product { Id = 3, Name = "Product3", Price = 20 }, p => p.Price);
productLists.AddItem(new Product { Id = 4, Name = "Product4", Price = 20 }, p => p.Price);
productLists.AddItem(new Product { Id = 5, Name = "Product5", Price = 15 }, p => p.Price);
foreach (var x in productLists)
Console.WriteLine($"{x.Key} {string.Join("|", x.Value.Select(p => p.Name))}");
outputs:
10 Product1|Product2
15 Product5
20 Product3|Product4
CodePudding user response:
You could calculate the position of the new element before adding it to the list, and then use List.Insert.