2010-09-03 7 views
2

Je résoudre ce problème de la rotation d'un tableau et obtenu algorithme et le code de travailFaire pivoter un tableau en utilisant la syntaxe LINQ

int[] Rotate(int[] ar,int k) 
     { 
      if (k <= 0 || k > ar.Length - 1) 
       return ar; 
      Reverse(ar, 0, k - 1); 
      Reverse(ar, k, ar.Length - 1); 
      Reverse(ar, 0, ar.Length - 1); 
      return ar;    
     } 

void Reverse(int[] ar,int start, int end) 
     { 
      while (start < end) 
      { 
       int temp = ar[start]; 
       ar[start] = ar[end]; 
       ar[end] = temp; 
       start++; 
       end--; 
      } 
     } 

Maintenant, je veux faire dans LINQ et moi avons le code ci-dessous, je pense que cela peut être fait beaucoup mieux.

int[] Rotate(int[] ar,int k) 
    { 
     if (k <= 0 || k > ar.Length - 1) 
      return ar; 
     int[] ar1=ar.Take(k-1).Reverse().ToArray(); 
     int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray(); 
     int[] ar3 = ar1.Concat(ar2).Reverse().ToArray(); 
     return ar3; 
    } 

Ceci est un algorithme bien connu de perles de programmation - http://books.google.com/books?id=kse_7qbWbjsC&lpg=PA14&ots=DfzTzQCSar&dq=rotate%20an%20array%20programming%20pearls&pg=PA14#v=onepage&q&f=false

Et en général comment développer mes compétences LINQ, si on me donne un problème de programmation, en ce moment je ne pense à des boucles ou foreach boucles, comment penser en termes d'opérateurs linq. Je lis C# 4.0 en bref, autre que de pratiquer des conseils?

+0

Ceci est la syntaxe * de la méthode d'extension *. La syntaxe LINQ commence avec 'from ...'. –

+0

Oui, mais en utilisant LINQ pour se référer à lambdas/Enumerable ... Je crains que le chat soit bien sorti du lot. :( –

+2

@Marcelo Cantos, ce que vous appelez est appelé la * syntaxe de compréhension de la requête * Il n'y a pas de "syntaxe LINQ" –

Répondre

3

A partir de votre code:

int[] ar1=ar.Take(k-1).Reverse().ToArray(); 
int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray(); 
int[] ar3 = ar1.Concat(ar2).Reverse().ToArray(); 

Puisque vous voulez juste obtenir tous les éléments restants, la Prenez dans la deuxième ligne n'est pas nécessaire. Ar1 et ar2 sont juste énumérés, donc ils n'ont pas besoin d'être des tableaux. Les appels ToArray ne sont pas nécessaires. Avec un peu de changement de nom créatif jeté dans, nous avons:

IEnumerable<int> revFirst = ar.Take(k-1).Reverse(); 
IEnumerable<int> revLast = ar.Skip(k-1).Reverse(); 
int[] ar3 = revFirst.Concat(revLast).Reverse().ToArray(); 

Maintenant, nous avons

rev (rev (premier) + rev (dernier))

distribuer le rev externe donne

rev (rev (dernier)) + rev (rev (premier))

qui est le même que

last + first 

appliquant les mêmes opérations au code donne

IEnumerable<int> first = ar.Take(k-1); 
IEnumerable<int> last = ar.Skip(k-1); 
int[] ar3 = last.Concat(first).ToArray(); 

ce qui simplifie encore à

int[] ar3 = ar.Skip(k-1).Concat(ar.Take(k-1)).ToArray(); 

et nous avons maintenant la réponse de Jon Skeet nous devons donc être fait.

+0

J'aime que vous sachiez que vous avez terminé lorsque votre réponse correspond à celle de Jon. – RichK

+0

Explication merveilleuse! Merci d'avoir répondu à ma réponse et à la réponse de Jon et de la déduire de la mienne, un grand effort! – satyajit

13

Je ne sais pas pourquoi vous avez tous les retournements, pour être honnête. Que diriez-vous ceci:

int[] Rotate(int[] ar,int k) 
{ 
    if (k <= 0 || k > ar.Length - 1) 
     return ar; 
    return ar.Skip(k)   // Start with the last elements 
      .Concat(ar.Take(k)) // Then the first elements 
      .ToArray();   // Then make it an array 
} 

Voici un programme court mais complet pour le démontrer:

using System; 
using System.Linq; 

class Test 
{ 
    static int[] Rotate(int[] ar,int k) 
    { 
     if (k <= 0 || k > ar.Length - 1) 
      return ar; 
     return ar.Skip(k)   // Start with the last elements 
       .Concat(ar.Take(k)) // Then the first elements 
       .ToArray();   // Then make it an array 
    } 

    static void Main() 
    { 
     int[] values = { 1, 2, 3, 4, 5 }; 
     int[] rotated = Rotate(values, 3); 

     Console.WriteLine(string.Join(", ", rotated)); 
    } 
} 

Sortie: 4, 5, 1, 2, 3

EDIT: Je viens de remarquer une différence majeure entre mon code et votre original: le vôtre modifie le tableau d'origine - le mien renvoie un nouveau tableau nouveau avec les valeurs tournées. De même que votre code LINQ, mais cela signifie que si vous étiez en train de tester mon code avec quelque chose qui ne regardait que le tableau d'origine, vous ne verriez pas la rotation.

LINQ est conçu pour fonctionner de cette manière en général - il favorise le retour d'une nouvelle séquence plutôt que la modification d'une séquence existante.

+0

Ceci ne fait pas tourner le tableau pour moi, il retourne juste le tableau original. – satyajit

+0

@satyajit: Ensuite, vous ne l'utiliserez pas correctement, je vais ajouter un programme court mais complet pour le montrer: –

+0

Oui, j'ai compris que votre code renvoyait un nouveau tableau. pour m'expliquer! – satyajit