2014-07-24 12 views
-2

je la paix de code suivant, que les facteurs d'un int aux nombres premiers:Refactor une boucle de laide dans LINQ

private static IEnumerable<int> Factor(int input) 
    { 
     IList<int> result = new List<int>(); 

     while (true) 
     { 
      var theSmallestDivisor = GetTheSmallestDivisor(input); 
      if (theSmallestDivisor == 0) 
      { 
       result.Add(input); 
       return result; 
      } 

      result.Add(theSmallestDivisor); 
      input = input/theSmallestDivisor; 
     } 
    } 

Je suis à la recherche pour obtenir des conseils sur la façon d'améliorer, éventuellement en utilisant LINQ.

+3

Quel est le problème avec la boucle que vous avez? Je ne vois pas LINQ aider ici. Vous n'écrivez pas une requête. – BradleyDotNET

+6

Nouveau marteau brillant (LINQ) ... tout ressemble à un clou :) –

+0

Eh bien, LINQ ne se limite pas aux requêtes, malgré son nom. Le code actuel est de 14 lignes, s'il y a une ligne LINQ alternative je serais très heureux. –

Répondre

5

Voici une version iterator:

private static IEnumerable<int> Factor(int input) 
{ 
    while (true) 
    { 
     var theSmallestDivisor = GetTheSmallestDivisor(input); 
     if (theSmallestDivisor == 0) 
     { 
      yield return input; 
      yield break; 
     } 

     yield return theSmallestDivisor; 
     input = input/theSmallestDivisor; 
    } 
} 

LINQ ne ferait que rendre ce code moins lisible dans ce cas particulier.

+0

Merci Lucas, ça a l'air plutôt bien. Je me demande s'il existe un moyen d'éliminer l'affectation 'input = input/theSmallestDivisor' et d'avoir un programme plus fonctionnel avec des valeurs immuables. –

+0

Eh bien ... parfait est l'ennemi du bien, et c'est assez bon assez IMO. Si vous voulez un style fonctionnel, vous devrez utiliser la récursivité, qui sera plus lente, plus encline à empiler des débordements, et plus difficile à lire, ou à faire quelque chose de compliqué pour éviter la récursivité. Oh, et vous pouvez utiliser 'input/= theSmallestDivisor;' si vous préférez;) –

-1
public IEnumerable<int> GetFactors(int input) 
{ 
    int first = Primes() 
     .TakeWhile(x => x <= Math.Sqrt(input)) 
     .FirstOrDefault(x => input % x == 0); 
    return first == 0 
      ? new[] { input } 
      : new[] { first }.Concat(GetFactors(input/first)); 
} 
+2

D'où vient «Primes»? – paqogomez

+0

Vous pensez vraiment être * meilleur * que l'exemple donné? Plus intelligent peut-être, mais ce n'est pas vraiment le même algorithme, et c'est très difficile à comprendre/lire. – BradleyDotNET

+0

Qu'est-ce que 'Primes()'? – Shiva

3

Les opérateurs LINQ sont principalement conçus pour générer une nouvelle liste à partir d'une liste existante. par exemple. Pas tellement pour générer une liste à partir de zéro comme vous essayez de le faire.

Mais, puisque vous revenez IEnumerable, vous pouvez aussi bien le rendre paresseux:

private static IEnumerable<int> Factor(int input) 
{ 
    while (true) 
    { 
     var theSmallestDivisor = GetTheSmallestDivisor(input); 
     if (theSmallestDivisor == 0) 
     { 
      yield return input; 
      yield break; 
     } 

     yield return theSmallestDivisor; 
     input = input/theSmallestDivisor; 
    } 
} 
Questions connexes