none
Best C# collection for inventory RRS feed

  • Question

  • Hi all,

    I have a need to setup a collection for something similar to a kitchen pantry.  The collection needs random access, sortable, and keys need to be duplicatable.  Being fast would be icing on the cake.

    The pantry would store up to 10 'slots' for items, each slot can hold 10 of the same item, and slots can be duplicates.

    For instance, if my pantry was a Dictionary<string, int>  (in readable terms: Dictionary<item_Name, count> )

    Ginger, 8
    Garlic, 3
    Onion Powder, 10

    In my situation, someone might need to add another onion powder to the pantry, but the current onion powder slot is full, therefore they'd start a new Onion Powder slot with a count of 1 in it.

    Ginger, 8
    Garlic, 3
    Onion Powder, 10
    Onion Powder, 1

    What's the best collection to use here?

    Thanks in advance

    Thursday, July 18, 2019 8:31 PM

All replies

  • Greetings Synergyauto71.

    I would create a class called, say, Condiment, which would have fields for the name and quantity and a static field for the maximum quantity. Then I would create a List<Condiment> to hold the contents of the pantry. Or perhaps create a new class called CondimentList, which would be derived from List but have its own methods for sorting, adding and so on. The Add method, for example, would check for an existing entry of the same name and create a new entry if there isn't one or if there is but the quantity is already at the max, but would increment the quantity of the existing entry otherwise.

    Thursday, July 18, 2019 11:32 PM
  • Something like this? I have concerns about the Add() method, specifically the foreach that loops over any slots that have the item being inserted. From experience one class <> another one being compared to it, and my overrides of Equals and GetHashCode have been less than successful.

    public class InventoryItem 
        {
            public InventoryItem() { }
            public InventoryItem(IBaseItem _item, int _quantity, int _maxQuantity)
            {
                Item = _item;
                Quantity = _quantity;
                MaxQuantity = _maxQuantity;
    
            }
            public IBaseItem Item{ get; set; }
            public int Quantity { get; set; }
            public int MaxQuantity { get; set; }
        }
    
    public class InventoryList<T> : List<T>
        {
            public List<InventoryItem> Contents { get; set; }
            public int MaxSlots = 10;
    
            public InventoryList()
            {
                Contents = new List<InventoryItem>();
            }
    
            public int SlotCount()
            {
                return Contents.Count;
            }
            public bool HasFreeSlots()
            {
                return SlotCount() < MaxSlots;
            }
            public bool IsCompletelyFull()
            {
                return Contents.Sum(x => x.Quantity) >= Contents.Sum(x => x.MaxQuantity); 
            }
    
            public bool Add(InventoryItem ii)
            {
                //do all the checking before adding, return true/false for success
                foreach (var item in Contents.Where(i => i.Item == ii))
                {
                    if (item.Quantity < item.MaxQuantity)
                    {
                        item.Quantity++;
                        return true;
                    }
                }
                if (HasFreeSlots())
                {
                    Contents.Add(ii);
                }
                else
                    return false;
    
                return true;
            }
        }

    Friday, July 19, 2019 12:23 AM
  • A bit like that, but I think you're over-complicating it.

    namespace ConsoleApp
    {
       class Program
       {
          static void Main(string[] args)
          {
             InventoryItemList list = new InventoryItemList();
    
             list.Add("Ginger", 8);
             list.Add("Garlic", 3);
             list.Add("Onion Powder", 9);
    
             list.Add("Onion Powder", 1);
             list.Add("Onion Powder", 1);
    
             foreach (InventoryItem item in list)
             {
                Console.WriteLine("{0} {1}", item.Name, item.Quantity);
             }
          }
       }
    
       public class InventoryItem
       {
          public string Name{ get; set; }
          public int Quantity { get; set; }
    
          public static int MaxQuantity = 10;
    
          public InventoryItem(string name, int quantity)
          {
             Name = name;
             Quantity = quantity;
          }
    
       }
    
       public class InventoryItemList : List<InventoryItem>
       {
    
          // Overload for adding a new item. The 'new' keyword hides the base method of the same name.
          public new void Add(InventoryItem item)
          {
             Add(item.Name, item.Quantity);
          }
    
          // Overload for adding a new name and quantity.
          public void Add(string name, int quantity)
          {
             foreach (InventoryItem item in this)
             {
                if (item.Name == name)
                {
                   item.Quantity += quantity;
                   if (item.Quantity > InventoryItem.MaxQuantity)
                   {
                      base.Add(new InventoryItem(name, item.Quantity - InventoryItem.MaxQuantity));
                      item.Quantity = InventoryItem.MaxQuantity;
                   }
                   return; 
                }
             }
    
             base.Add(new InventoryItem(name, quantity));
          }
    
       }
    }
    

    One problem with this code is that if we were to add another Onion Powder, the Add method would find the one with a quantity of 10, think it's past the maximum, and hence add another new one with a quantity of 1 (instead of going on and finding the one with a quantity of 1 that's already there and adding to that). So the Add method will need some more smarts to deal with that case. But that's the general idea.

    • Proposed as answer by Synergyauto Friday, July 19, 2019 3:36 AM
    Friday, July 19, 2019 1:26 AM
  • Thank you much Ante, this is a great start! 
    Friday, July 19, 2019 3:28 AM