Easiest way to Rotate a List in c#

后端 未结 16 3135
鱼传尺愫
鱼传尺愫 2020-12-01 07:06

Lists say I have a list List {1,2,3,4,5}

Rotate means:

=> {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3}
相关标签:
16条回答
  • 2020-12-01 07:48

    I've used the following extensions for this:

    static class Extensions
    {
        public static IEnumerable<T> RotateLeft<T>(this IEnumerable<T> e, int n) =>
            n >= 0 ? e.Skip(n).Concat(e.Take(n)) : e.RotateRight(-n);
    
        public static IEnumerable<T> RotateRight<T>(this IEnumerable<T> e, int n) =>
            e.Reverse().RotateLeft(n).Reverse();
    }
    

    They're certainly easy (OP title request), and they've got reasonable performance (OP write-up request). Here's a little demo I ran in LINQPad 5 on an above-average-powered laptop:

    void Main()
    {
        const int n = 1000000;
        const int r = n / 10;
        var a = Enumerable.Range(0, n);
    
        var t = Stopwatch.StartNew();
    
        Console.WriteLine(a.RotateLeft(r).ToArray().First());
        Console.WriteLine(a.RotateLeft(-r).ToArray().First());
        Console.WriteLine(a.RotateRight(r).ToArray().First());
        Console.WriteLine(a.RotateRight(-r).ToArray().First());
    
        Console.WriteLine(t.ElapsedMilliseconds); // e.g. 236
    }
    
    0 讨论(0)
  • 2020-12-01 07:51

    You can use below code for left Rotation.

    List<int> backUpArray = array.ToList();
    
    for (int i = 0; i < array.Length; i++)
    {
        int newLocation = (i + (array.Length - rotationNumber)) % n;
        array[newLocation] = backUpArray[i];
    }
    
    0 讨论(0)
  • 2020-12-01 07:53

    You can play nice in .net framework.

    I understand that what you want to do is more up to be an iteration behavior than a new collection type; so I would suggest you to try this extension method based on IEnumerable, which will work with Collections, Lists and so on...

    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
    
            IEnumerable<int> circularNumbers = numbers.AsCircular();
    
            IEnumerable<int> firstFourNumbers = circularNumbers
                .Take(4); // 1 2 3 4
    
            IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers
                .Skip(4).Take(7); // 4 5 6 7 1 2 3 
        }
    }
    
    public static class CircularEnumerable
    {
        public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source)
        {
            if (source == null)
                yield break; // be a gentleman
    
            IEnumerator<T> enumerator = source.GetEnumerator();
    
            iterateAllAndBackToStart:
            while (enumerator.MoveNext()) 
                yield return enumerator.Current;
    
            enumerator.Reset();
            if(!enumerator.MoveNext())
                yield break;
            else
                yield return enumerator.Current;
    goto iterateAllAndBackToStart;
        }
    }
    
    • Reasonable performance
    • Flexible

    If you want go further, make a CircularList and hold the same enumerator to skip the Skip() when rotating like in your sample.

    0 讨论(0)
  • 2020-12-01 07:54

    I use this one:

    public static List<T> Rotate<T>(this List<T> list, int offset)
    {
        return list.Skip(offset).Concat(list.Take(offset)).ToList();
    }
    
    0 讨论(0)
提交回复
热议问题