Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here is a C# solution to that problem I came up with a little while back when asked the same question. It implements Add, Remove, Contains, and Random along with other standard .NET interfaces. Not that you would ever need to implement it in such detail during an interview but it's nice to have a concrete solution to look at...</p> <pre class="lang-cs prettyprint-override"><code>using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; /// &lt;summary&gt; /// This class represents an unordered bag of items with the /// the capability to get a random item. All operations are O(1). /// &lt;/summary&gt; /// &lt;typeparam name="T"&gt;The type of the item.&lt;/typeparam&gt; public class Bag&lt;T&gt; : ICollection&lt;T&gt;, IEnumerable&lt;T&gt;, ICollection, IEnumerable { private Dictionary&lt;T, int&gt; index; private List&lt;T&gt; items; private Random rand; private object syncRoot; /// &lt;summary&gt; /// Initializes a new instance of the &lt;see cref="Bag&amp;lt;T&amp;gt;"/&gt; class. /// &lt;/summary&gt; public Bag() : this(0) { } /// &lt;summary&gt; /// Initializes a new instance of the &lt;see cref="Bag&amp;lt;T&amp;gt;"/&gt; class. /// &lt;/summary&gt; /// &lt;param name="capacity"&gt;The capacity.&lt;/param&gt; public Bag(int capacity) { this.index = new Dictionary&lt;T, int&gt;(capacity); this.items = new List&lt;T&gt;(capacity); } /// &lt;summary&gt; /// Initializes a new instance of the &lt;see cref="Bag&amp;lt;T&amp;gt;"/&gt; class. /// &lt;/summary&gt; /// &lt;param name="collection"&gt;The collection.&lt;/param&gt; public Bag(IEnumerable&lt;T&gt; collection) { this.items = new List&lt;T&gt;(collection); this.index = this.items .Select((value, index) =&gt; new { value, index }) .ToDictionary(pair =&gt; pair.value, pair =&gt; pair.index); } /// &lt;summary&gt; /// Get random item from bag. /// &lt;/summary&gt; /// &lt;returns&gt;Random item from bag.&lt;/returns&gt; /// &lt;exception cref="System.InvalidOperationException"&gt; /// The bag is empty. /// &lt;/exception&gt; public T Random() { if (this.items.Count == 0) { throw new InvalidOperationException(); } if (this.rand == null) { this.rand = new Random(); } int randomIndex = this.rand.Next(0, this.items.Count); return this.items[randomIndex]; } /// &lt;summary&gt; /// Adds the specified item. /// &lt;/summary&gt; /// &lt;param name="item"&gt;The item.&lt;/param&gt; public void Add(T item) { this.index.Add(item, this.items.Count); this.items.Add(item); } /// &lt;summary&gt; /// Removes the specified item. /// &lt;/summary&gt; /// &lt;param name="item"&gt;The item.&lt;/param&gt; /// &lt;returns&gt;&lt;/returns&gt; public bool Remove(T item) { // Replace index of value to remove with last item in values list int keyIndex = this.index[item]; T lastItem = this.items[this.items.Count - 1]; this.items[keyIndex] = lastItem; // Update index in dictionary for last item that was just moved this.index[lastItem] = keyIndex; // Remove old value this.index.Remove(item); this.items.RemoveAt(this.items.Count - 1); return true; } /// &lt;inheritdoc /&gt; public bool Contains(T item) { return this.index.ContainsKey(item); } /// &lt;inheritdoc /&gt; public void Clear() { this.index.Clear(); this.items.Clear(); } /// &lt;inheritdoc /&gt; public int Count { get { return this.items.Count; } } /// &lt;inheritdoc /&gt; public void CopyTo(T[] array, int arrayIndex) { this.items.CopyTo(array, arrayIndex); } /// &lt;inheritdoc /&gt; public bool IsReadOnly { get { return false; } } /// &lt;inheritdoc /&gt; public IEnumerator&lt;T&gt; GetEnumerator() { foreach (var value in this.items) { yield return value; } } /// &lt;inheritdoc /&gt; IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } /// &lt;inheritdoc /&gt; public void CopyTo(Array array, int index) { this.CopyTo(array as T[], index); } /// &lt;inheritdoc /&gt; public bool IsSynchronized { get { return false; } } /// &lt;inheritdoc /&gt; public object SyncRoot { get { if (this.syncRoot == null) { Interlocked.CompareExchange&lt;object&gt;( ref this.syncRoot, new object(), null); } return this.syncRoot; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload