Home > Back-end >  insert item in correct position in a c# list
insert item in correct position in a c# list

Time:11-29

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.

  • Related