2

Let's say I want a sequence of 10 numbers, and I have a function which produces numbers on demand:

var s = new List<int>();
for (var i=0; i<10; i++) {
    s.Add(Magically_generate_a_very_special_number());
}

Is the usual way of accomplishing this. However, let's say I want to use LINQ. I can already do (let's ignore the distinction between types):

var s = Enumerable.Range(0, 10).Select(i => MathNet.Numerics.Statistics.DescriptiveStatistics())

Which is almost good enough for me. However, it bothers me that I need to specify a range of integers first - this is a superfluous step since I discard the value anyway. Is it possible to do something like the following?

var s = Enumerable.ObjectMaker(Magically_generate_a_very_special_number).Take(10);

It seems that Enumerable.Repeat almost does what I want, but it takes the result of the function I give it and then duplicates that, instead of repeatedly evaluating the function.

By the way, the inspiration for this question was the Math.Net IContinuousDistribution.Samples method. Its body looks like the following:

while (true)
{
    yield return Generate_a_random_number();
}

So that you can obtain a sequence of samples from the distribution with myDistribution.Samples.Take. In principle, I could just write my own method to produce an iterator in the same way, but I'm wondering if there is one that already exists.

2
  • I may be really out of line here but IMHO, purpose of LINQ is to reduce number of lines of code and to select certain elements from an enumerable based on certain conditions or not. It is not really intended to create new objects. Commented Dec 24, 2013 at 14:05
  • No, that's a perfectly reasonably comment. However, to me, in some cases, the LINQ is easier to read (in my own personal projects). Commented Dec 24, 2013 at 14:28

5 Answers 5

2

You could try using the foreach method :

Enumerable.Take(10).ToList().Foreach(Magically_generate_a_very_special_number);

Downside imho is that you have to do a ToList in between.

edit misread question, so nvmd :)

Sign up to request clarification or add additional context in comments.

4 Comments

Actually I meant foreach the loop, not Foreach the method. Your code is almost what I want... But why do I need to call ToList?
@Superbest because the extension method Foreach is defined on List<T>, not IEnumerable<T>.
@Vache ForEach is neither an extension method nor a LINQ method, despite what many believe. It is a List<T> method dating back to .NET 2.0.
@MatthewFerreira Indeed! Thanks for the correction, I'll keep that in mind.
1

You could create a sequence of 10 method delegates referencing your Magically_generate_a_very_special_number method, then invoke them consecutively.

var s = Enumerable.Repeat<Func<int>>(generate, 10).Select(f => f());

Comments

1

I don’t think anything like your Enumerable.ObjectMaker exists as a convenient part of LINQ, but you can make one exactly like it.

public static IEnumerable<T> ObjectMaker<T>(Func<T> generator) {
    while (true)
        yield return generator();
}
var s = ObjectMaker(MagicallyGenerateVerySpecialNumber).Take(10);

Comments

0

I agree with danish: I think trying to do it in base linq is uglier and harder to read than just doing it in a for loop. Seems to defeat the purpose of linq.

That said, maybe you can make an extension method. So long as your Magically_generate_a_very_special_number function doesn't require parameters, something like this should do what you're after:

public static void Fill<T>(this IList<T> list, int repeat, Func<T> fn) {
    for (int i = 0; i < repeat; i++) list.Add(fn());
}

Then use like this:

s.Fill(10, Magically_generate_a_very_special_number);

Comments

0

We can create a new method to generate N objects by calling a generation function N times that follows the general pattern of LINQ methods, so that you have something that fits your exact needs:

public static IEnumerable<T> Generate<T>(Func<T> generator, int count)
{
    for (int i = 0; i < count; i++)
        yield return generator();
}

And now you can write:

var numbers = Generate(Magically_generate_a_very_special_number, 10);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.