Comment écrire une expression LINQ (syntaxe d'appel de méthode préférée) qui donne une liste de nombres de fibonacci compris dans une certaine plage, disons 1 à 1000?Aide pour l'expression LINQ
Répondre
OK; pour une plus « FP » Réponse:
using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
static void Main()
{
Func<long, long, long, IEnumerable<long>> fib = null;
fib = (n, m, cap) => n + m > cap ? Enumerable.Empty<long>()
: Enumerable.Repeat(n + m, 1).Concat(fib(m, n + m, cap));
var list = fib(0, 1, 1000).ToList();
}
}
Notez que en théorie cela peut être écrit comme une seule lambda, mais qui est very hard.
En utilisant la réponse iterator bloc de here:
foreach (long i in Fibonacci()
.SkipWhile(i => i < 1)
.TakeWhile(i => i <= 1000)) {
Console.WriteLine(i);
}
ou pour une liste:
var list = Fibonacci().SkipWhile(i => i < 1).TakeWhile(i => i <= 1000)
.ToList();
Sortie:
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
Je veux une solution qui n'utilise aucune boucle. Seules les méthodes LINQ sont autorisées. – missingfaktor
Et que pensez-vous que la plupart des LINQ (-to-objects) sont sous le capot? Plus sérieusement; Qu'avez-vous exactement en tête? Si vous voulez dire à l'appelant, ajoutez simplement '.ToArray()' ou '.ToList()'. Si vous voulez dire dans la mise en œuvre, bien - c'est une séquence infinie ... vous devrez peut-être boucler à un moment donné ... –
Je joue avec la programmation fonctionnelle et je ne veux donc pas de boucles explicites. C'est tout. – missingfaktor
Voici la solution de base de l'énumérateur. C'est une évaluation paresseuse. Le prochain numéro est généré lorsque MoveNext() est terminé.
foreach (int k in Fibonacci.Create(10))
Console.WriteLine(k);
class Fibonacci : IEnumerable<int>
{
private FibonacciEnumertor fibEnum;
public Fibonacci(int max) {
fibEnum = new FibonacciEnumertor(max);
}
public IEnumerator<int> GetEnumerator() {
return fibEnum;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public static IEnumerable<int> Create(int max) {
return new Fibonacci(max);
}
private class FibonacciEnumertor : IEnumerator<int>
{
private int a, b, c, max;
public FibonacciEnumertor(int max) {
this.max = max;
Reset();
}
// 1 1 2 3 5 8
public int Current {
get {
return c;
}
}
public void Dispose() {
}
object System.Collections.IEnumerator.Current {
get { return this.Current; }
}
public bool MoveNext() {
c = a + b;
if (c == 0)
c = 1;
a = b;
b = c;
;
return max-- > 0;
}
public void Reset() {
a = 0;
b = 0;
}
}
}
Ce qui est amusant, c'est que lorsque le compilateur a fini de le corriger, ce n'est pas très différent de l'approche de l'itérateur. écrivez ;-p –
Vous avez raison, ce sera similaire à l'itératif. En fait ce que je voulais, c'est donner le même comportement que suivre. Enumerable.Range (1, 100); Le code est peut-être volumineux, mais il est réutilisable et n'entraîne aucune baisse de performance. – affan
pas très performant:
val fibonacci = Enumerable
.Range(0, 1000)
.Aggregate(new List<int>{1,0}, (b,j)=>{
b.Insert(0,b[0]+b[1]);
return b; });
fin, mais une version rapide avec le mot-clé "rendement" :-)
IEnumerable<int> Fibonacci(int limit)
{
int number = 1, old = 0;
while (number < limit)
{
yield return number;
int tmp = number; number += old; old = tmp;
}
}
var list = Fibonacci(1000).ToList();
plus facile pour imprimer fibonacci LINQ
List<int> lst = new List<int> { 0, 1 };
for (int i = 0; i <= 10; i++)
{
int num = lst.Skip(i).Sum();
lst.Add(num);
foreach (int number in lst)
Console.Write(number + " ");
Console.WriteLine();
}
Exactement ce dont j'avais besoin. Merci. :) – missingfaktor
putain, que quelque impressionnant LINQ. +1 –
Impressionnant LINQ? Cela ressemble plus à la programmation fonctionnelle 101 pour moi. Pourtant, pour les programmeurs C# les plus impératifs, il est forcément très impressionnant. – peSHIr