Maneira mais fácil de rodar uma lista em c #

Listas dizem que tenho uma lista List {1,2,3,4,5}

Rodar significa:

 => {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3} 

Talvez girar não seja a melhor palavra para isso, mas espero que você entenda o que eu quero dizer

Minha pergunta, o que é a maneira mais fácil (em código curto, c # 4 Linq pronto), e não será atingido pelo desempenho (desempenho razoável)

Obrigado.

Você poderia implementá-lo como uma fila. Dequeue e enfileire o mesmo valor.

** Eu não tinha certeza sobre o desempenho na conversão de uma Lista para uma Fila, mas as pessoas votaram em meu comentário, então estou postando isso como uma resposta.

List

A maneira mais simples (para uma List ) é usar:

 int first = list[0]; list.RemoveAt(0); list.Add(first); 

O desempenho é desagradável embora – O (n).

Matriz

Isso é basicamente equivalente à versão List , mas mais manual:

 int first = array[0]; Array.Copy(array, 1, array, 0, array.Length - 1); array[array.Length - 1] = first; 

LinkedList

Se você pudesse usar um LinkedList , isso seria muito mais simples:

 int first = linkedList.First; linkedList.RemoveFirst(); linkedList.AddLast(first); 

Este é O (1), pois cada operação é constante.

Queue

A solução de cadrell0 de usar uma fila é uma única instrução, pois o Dequeue remove o elemento e o retorna:

 queue.Enqueue(queue.Dequeue()); 

Embora não seja possível encontrar nenhuma documentação da característica de desempenho disso, eu esperaria que o Queue fosse implementado usando uma matriz e um índice como o “ponto de partida virtual” – caso em que este é outro O (1) solução.

Observe que em todos esses casos você deseja verificar se a lista está vazia primeiro. (Você poderia considerar isso como um erro ou um não-op.)

Eu uso este:

 public static List Rotate(this List list, int offset) { return list.Skip(offset).Concat(list.Take(offset)).ToList(); } 

Parece que alguns respondedores trataram isso como uma chance de explorar estruturas de dados. Embora essas respostas sejam informativas e úteis, elas não são muito lineares.

A abordagem Linq’ish é: Você obtém um método de extensão que retorna um IEnumerable preguiçoso que sabe como construir o que você deseja. Este método não modifica a fonte e só deve alocar uma cópia da fonte, se necessário.

 public static IEnumerable> Rotate(this List source) { for(int i = 0; i < source.Length; i++) { yield return source.TakeFrom(i).Concat(source.TakeUntil(i)); } } //similar to list.Skip(i-1), but using list's indexer access to reduce iterations public static IEnumerable TakeFrom(this List source, int index) { for(int i = index; i < source.Length; i++) { yield return source[i]; } } //similar to list.Take(i), but using list's indexer access to reduce iterations public static IEnumerable TakeUntil(this List source, int index) { for(int i = 0; i < index; i++) { yield return source[i]; } } 

Usado como:

 List myList = new List(){1, 2, 3, 4, 5}; foreach(IEnumerable rotation in myList.Rotate()) { //do something with that rotation } 

Que tal agora:

 var output = input.Skip(rot) .Take(input.Count - rot) .Concat(input.Take(rot)) .ToList(); 

Onde rot é o número de pontos a serem rotacionados – que deve ser menor que o número de elementos na lista de input .

Como @cadrell0 resposta mostra se isso é tudo que você faz com sua lista, você deve usar uma fila em vez de uma lista.

Minha solução talvez seja muito básica (eu não gostaria de dizer que é lame …) e não LINQ’ish.
No entanto, tem um desempenho muito bom.

 int max = 5; //the fixed size of your array. int[] inArray = new int[5] {0,0,0,0,0}; //initial values only. void putValueToArray(int thisData) { //let's do the magic here... Array.Copy(inArray, 1, inArray, 0, max-1); inArray[max-1] = thisData; } 

Experimentar

 List nums = new List {1,2,3,4,5}; var newNums = nums.Skip(1).Take(nums.Count() - 1).ToList(); newNums.Add(nums[0]); 

Embora, eu goste da resposta de Jon Skeet melhor.

Minha solução para matrizes:

  public static void ArrayRotate(Array data, int index) { if (index > data.Length) throw new ArgumentException("Invalid index"); else if (index == data.Length || index == 0) return; var copy = (Array)data.Clone(); int part1Length = data.Length - index; //Part1 Array.Copy(copy, 0, data, index, part1Length); //Part2 Array.Copy(copy, part1Length, data, 0, index); } 

Você pode usar o código abaixo para a rotação à esquerda.

 List backUpArray = array.ToList(); for (int i = 0; i < array.Length; i++) { int newLocation = (i + (array.Length - rotationNumber)) % n; array[newLocation] = backUpArray[i]; } 

Você pode jogar bem no framework .net.

Eu entendo que o que você quer fazer é mais um comportamento de iteração do que um novo tipo de coleção; então eu sugiro que você tente este método de extensão baseado em IEnumerable, que irá trabalhar com collections, listas e assim por diante …

 class Program { static void Main(string[] args) { int[] numbers = { 1, 2, 3, 4, 5, 6, 7 }; IEnumerable circularNumbers = numbers.AsCircular(); IEnumerable firstFourNumbers = circularNumbers.Take(4); // 1 2 3 4 IEnumerable nextSevenNumbersfromfourth = circularNumbers .Skip(4).Take(7); // 4 5 6 7 1 2 3 } } public static class CircularEnumerable { public static IEnumerable AsCircular(this IEnumerable source) { if (source == null) yield break; // be a gentleman IEnumerator 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; } } 
  • Desempenho razoável
  • Flexível

Se você quiser ir mais longe, faça um CircularList e mantenha o mesmo enumerador para pular o Skip() ao girar como em sua amostra.

Eu usei as seguintes extensões para isso:

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

Eles são certamente fáceis (solicitação de título OP), e eles têm um desempenho razoável (solicitação de write-up OP). Aqui está um pequeno demo que eu corri no LINQPad 5 em um laptop acima da média:

 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); // eg 236 } 

abaixo está minha abordagem. Obrigado

 public static int[] RotationOfArray(int[] A, int k) { if (A == null || A.Length==0) return null; int[] result =new int[A.Length]; int arrayLength=A.Length; int moveBy = k % arrayLength; for (int i = 0; i < arrayLength; i++) { int tmp = i + moveBy; if (tmp > arrayLength-1) { tmp = + (tmp - arrayLength); } result[tmp] = A[i]; } return result; } 
 public static int[] RightShiftRotation(int[] a, int times) { int[] demo = new int[a.Length]; int d = times,i=0; while(d>0) { demo[d-1] = a[a.Length - 1 - i]; d = d - 1; i = i + 1; } for(int j=a.Length-1-times;j>=0;j--) { demo[j + times] = a[j]; } return demo; } 

Usando o Linq,

 List temp = new List(); public int[] solution(int[] array, int range) { int tempLength = array.Length - range; temp = array.Skip(tempLength).ToList(); temp.AddRange(array.Take(array.Length - range).ToList()); return temp.ToArray(); } 

Fui solicitado a reverter um array de caracteres com um uso mínimo de memory.

char[] charArray = new char[]{'C','o','w','b','o','y'};

Método:

 static void Reverse(ref char[] s) { for (int i=0; i < (s.Length-i); i++) { char leftMost = s[i]; char rightMost = s[s.Length - i - 1]; s[i] = rightMost; s[s.Length - i - 1] = leftMost; } } 

Que tal usar aritmética modular:

 public void UsingModularArithmetic() { string[] tokens_n = Console.ReadLine().Split(' '); int n = Convert.ToInt32(tokens_n[0]); int k = Convert.ToInt32(tokens_n[1]); int[] a = new int[n]; for(int i = 0; i < n; i++) { int newLocation = (i + (n - k)) % n; a[newLocation] = Convert.ToInt32(Console.ReadLine()); } foreach (int i in a) Console.Write("{0} ", i); } 

Então, basicamente, adicionando os valores para a matriz quando estou lendo do console.