James Michael Hare

...hare-brained ideas from the realm of software development...
posts - 136 , comments - 1091 , trackbacks - 0

My Links

News

Welcome to my blog! I'm a Sr. Software Development Engineer in Seattle, WA. I've been doing C++/C#/Java development for over 18 years, but have definitely learned that there is always more to learn!

All thoughts and opinions expressed in my blog and my comments are my own and do not represent the thoughts of my employer.

Blogs I Read

MCC Logo MVP Logo

Follow BlkRabbitCoder on Twitter

Tag Cloud

Archives

Post Categories

C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

Once again, in this series of posts I look at the parts of the .NET Framework that may seem trivial, but can help improve your code by making it easier to write and maintain. The index of all my past little wonders posts can be found here.

So last week we covered the Enumerable.Range() method in the System.Linq namespace, which gives us a handy way to generate a sequence of integers to either use directly, or to feed into a more complex expression.  Today we’re going to look at another static method called Enumerable.Repeat() that allows us to repeat an element the specified number of times.

Using Repeat() to generate a sequence of a repeated value

Again, if we take a peek into the Enumerable static class in the System.Linq namespace, we see the vast array of LINQ extension methods, as well as a few static methods.  One of which is a method called Repeat() whose purpose is to generate a sequence of repeated occurrences of a given element.

It’s syntax looks like this:

  • Repeat(element, count)
    • Repeats the given element for the specified count. 

So given this, if we wanted to create an array of 10 occurrences of the same string, we could do so by coding:

   1: // Creates a sequence of 5 occurrences of "Hello World!" and then stores in array
   2: var repeatedValues = Enumerable.Repeat("Hello World!", 5).ToArray();

The main thing to notice in Repeat() is that it repeats the given element, it does not (at least not directly) repeatedly call an expression to generate multiple separate values.

For example, consider the following code:

   1: var ran = new Random();
   2:  
   3: // does this generate 100 random numers?  
   4: // Or repeat first random number 100 times?
   5: var repeatedRandom = Enumerable.Repeat(ran.Next(), 100);

What do we get?  Do we get a sequence of 100 random numbers?  Or a sequence of the first random number repeated 100 times? 

The answer is the latter.  The ran.Next() is resolved to get the value of the parameter, and then that result is the element that is repeated 100 times.  That is, if the first random number generated was 103242, then the array would contain { 103242, 103242, 103242, …, 103242 }.

So, we can repeat a single element several times, right?  Obviously if that’s what you needed to do then it’s right up your alley, but once again if we look past the simple examples, we see some more interesting other things that this also enables us to do.

Using Repeat() to turn a single item into a sequence of one item

One of the nice things about Repeat() is it allows us to easily represent a single item as a sequence of a single item.  For example, if you have a method that takes in an IEnumerable<T>, but you only have one T to give it, Repeat() makes it easy to pass in a sequence of length 1.

For example, if we had this method that takes an IEnumerabe<T> sequence of string:

   1: // method that takes a sequence of string
   2: public void AddElements(IEnumerable<string> elementSequence)
   3: {
   4:     // ...
   5: }

But we just wanted to pass the single string “EOF” into the method, we can use Repeat() to do so:

   1: // makes "EOF" into a sequence of 1 containing "EOF"
   2: AddElements(Enumerable.Repeat("EOF", 1));

So that’s a handy feature, though we could also, of course, do this by creating an explicit string[1] array or a List<string> as well.  In fact I have a blog post on Returning Zero or One Item As IEnumerable<T> (here) where I talk about this in more detail, including weighing the performance and mutability ramifications.

We could also create a sequence of size length 0, though this is a less interesting use of Repeat() as the element value would be unused and the Enumerable.Empty<T>() singleton generator is more efficient if we know the sequence is intended to be empty (again, see the above mentioned blog post for more details).

Using Repeat() to repeat a generator to create sequences

We said before that Repeat() can be used to repeat a given element a specific number of times.  This makes it sound like this can only be used to generate sequences of a repeated value.  While this is generally true when you consider Repeat() by itself, this is not necessarily true if you think beyond the element representing a simple value.

For example, let’s revisit the idea of creating a sequence of 100 random numbers, except this time, we will make the element a Func<int> that returns a random number.  So we will repeat the Func<int> 100 times, well wait, how does that help us?  Won’t we just get the same reference to the delegate repeated 100 times?  Well yes, but that’s not where we’ll end, we’ll then use Select() to invoke that delegate and return the result, giving us 100 random numbers:

   1: var ran = new Random();
   2:  
   3: // create a delegate from the method group,
   4: // repeat that delegate 100 times,
   5: // for each delegate, project it to its result,
   6: // convert to array.
   7: var results = Enumerable.Repeat<Func<int>>(ran.Next, 100)
   8:     .Select(f => f())
   9:     .ToArray();

Notice that we have to tell Repeat() that the type of element is a Func<int>, this is because it’s harder for the compiler to correctly infer the type Func<int> from a method group or delegate.  Also notice our element is ran.Next which is a method group and roughly equivalent to the lambda () => ran.Next().

So, that delegate reference is in a sequence 100 times, and for each item, the Select() projects it to the result from executing the delegate, which gives us a nice sequence of 100 random values.

Note that we could have gotten a similar result by using Enumerable.Range() as follows:

   1: var ran = new Random();
   2:  
   3: // create a sequence from 0 to 999 (1000 items),
   4: // for each int, project to the next random number,
   5: // convert to array
   6: var results = Enumerable.Range(0, 1000)
   7:     .Select(i => ran.Next())
   8:     .ToArray();

So in this method, we create a sequence of 1000 items (from 0 to 999) which we really don’t want to use, we’re more just using them to drive the Select() projection to return 1000 random numbers.  For more information on Range() see last week’s post on The Enumerable.Range() Static Method (here).

Both of these are similar ways to get the same results.  Some may prefer the first because Repeat() seems a more natural idiom than Range() for repeating a delegate, but it does have the baggage of creating two delegates (one for the generator, one for the projection) instead of the one for Range() (only requires the one for projection).

Which is better?  Execution-wise, the use of Range above is a hair faster (but really, the difference is very minor and of course that’s subject to change as the framework changes).  Other than that, it’s really up to you which way you prefer as they both accomplish the same goal. 

Summary

The Enumerable.Repeat() method performs the simple task of creating a sequence by repeating an element a specific number of times.  While this is, in of itself, a trivial need, it can also be used to drive more useful results such as repeating a generator delegate, or creating sequences out of single items.

Technorati Tags: , , , , , ,

Print | posted on Thursday, May 3, 2012 7:21 PM | Filed Under [ My Blog C# Software .NET Little Wonders ]

Feedback

Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

There's an easier way to generate random numbers:

var results = Enumerable.Repeat<Func<int>>(new Random(), 100).Select(r => r.Next()).ToArray();
5/4/2012 9:21 AM | Thomas Levesque
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

(oops, forgot to remove the "<Func<int>>" part...)
5/4/2012 9:22 AM | Thomas Levesque
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Thomas: Very nice! True, you could use the random number generator as the "element" and the Select() to project the next result. I like it!
5/4/2012 9:29 AM | James Michael Hare
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

var results = Enumerable.Repeat<Func<int>>(ran.Next, 100)
.Select(f => f())
.ToArray();

Surely this can just as well be written as:

var results = Enumerable.Range(0, 100)
.Select(i => ran.Next())
.ToArray();
5/7/2012 8:35 PM | Timwi
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

Damn, that’s exactly what you wrote, I just realised, but this crappy system doesn’t let me delete my comment :((
5/7/2012 8:36 PM | Timwi
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Timwi: No worries, I can delete your comment if you want. Shall I?
5/9/2012 9:16 AM | James Michael Hare
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

hm.....It's great coding :)
----
Watch EURO 2012 Live Stream https://sites.google.com/site/watcheuro2012livestream/
5/10/2012 1:18 AM | EURO 2012
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

I don't have anything to add to the discussion, but I just wanted to let you know that I've enjoyed reading your "Little *" posts for a while. Thanks for keeping them going!
5/10/2012 9:23 AM | Caleb Bell
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Caleb: Many thanks!
5/10/2012 3:38 PM | James Michael Hare
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Thomas: Erm, rather than running one generator 100 times you'd rather generate 100 objects? Come on now... I know this is .NET but still.
5/19/2012 12:54 PM | Anon
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Thomas: The RNG is seeded with the current time on new Random() (or was it time since system started?). Either way, that time isn't going to change fast enough to actually have a different seed all that often, so most (if not all) of the "random" values will be the same.
5/21/2012 7:55 AM | Daniel Rose
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Anon, @Daniel:

Actually, the new Random() is only created ONCE at the call to Repeat, and it's reference is used 100 times, it doesn't generate 100 unique instances of Random().
5/24/2012 11:29 AM | James Michael Hare
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

@Thomas,

the following does not even compile.

var results = Enumerable.Repeat<Func<int>>(new Random(), 100).Select(r => r.Next()).ToArray();
8/30/2013 11:25 AM | ray
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

Understand more @
http://www.dotnetlines.com/Blogs/tabid/85/EntryId/53/A-simple-way-to-provide-watermark-Text-to-ASP-NET-Textbox-with-TextMode-Password.aspx
12/15/2013 11:43 PM | Sac
Gravatar

# re: C#/.NET Little Wonders: The Enumerable.Repeat() Static Method

Understand more @
http://www.dotnetlines.com/Blogs/tabid/85/EntryId/54/Range-and-Repeat-Methods-in-LINQ-using-C.aspx
12/15/2013 11:44 PM | Sac
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 
 

Powered by: