Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>One suggestion I got elsewhere was to create a separate IArranger interface that describes a single operation to <strong>Arrange</strong> a collection. This can work where IComparer/IComparable cannot because it operates on an entire collection, instead of individual items. It might look something like this:</p> <pre><code>public interface IArranger&lt;T&gt; { IEnumerable&lt;T&gt; Arrange(IEnumerable&lt;T&gt; items); } </code></pre> <p>Then I could implement a <code>Shuffle</code> from the IArranger interface using a proper Fisher-Yates algorithm, and also have implementations that wrap each additional <code>IEnumerable.Sort()/IComparable/IComparer</code> varieties that I care about. That might look something like this:</p> <pre><code>public class ComparerArranger&lt;T&gt; : IArranger&lt;T&gt; { private IComparer&lt;T&gt; comparer; public ComparableArranger(IComparer&lt;T&gt; comparer) { this.comparer = comparer; } public IEnumerable&lt;T&gt; Arrange(IEnumerable&lt;T&gt; items) { return items.OrderBy(i =&gt; i, comparer); } } </code></pre> <p>or</p> <pre><code>//uses the default Comparer for the type (Comparer&lt;T&gt;.Default) public class TypeArranger&lt;T&gt; : IArranger&lt;T&gt; { public IEnumerable&lt;T&gt; Arrange(IEnumerable&lt;T&gt; items) { return items.OrderBy(i =&gt; i); } } </code></pre> <p>or</p> <pre><code>public class ShuffleArranger&lt;T&gt; : IArranger&lt;T&gt; { //naive implementation for demonstration // if I ever develop this more completely I would try to // avoid needing to call .ToArray() in here // and use a better prng private Random r = new Random(); public IEnumerable&lt;T&gt; Arrange(IEnumerable&lt;T&gt; items) { var values = items.ToArray(); //valid Fisher-Yates shuffle on the values array for (int i = values.Length; i &gt; 1; i--) { int j = r.Next(i); T tmp = values[j]; values[j] = values[i - 1]; values[i - 1] = tmp; } foreach (var item in values) yield return item; } } </code></pre> <p>For a final step, I add support for this to any IEnumerable via an extension method. Then you still get the simple run-time algorithm swapping, you have a better implementation of the shuffle algorithm, and the code to use it feels natural:</p> <pre><code>public static IEnumerable&lt;T&gt; Arrange(this IEnumerable&lt;T&gt; items, IArranger&lt;T&gt; arranger) { return arranger.Arrange(items); } </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