Simple Sequence Generation? - c#

I'm looking for an ultra-easy way to generate a list of numbers, 1-200.
(it can be a List, Array, Enumerable... I don't really care about the specific type)
Apparently .Net 4.0 has a Sequence.Range(min,max) method.
But I'm currently on .Net 3.5.
Here is a sample usage, of what I'm after, shown with Sequence.Range.
public void ShowOutput(Sequence.Range(1,200));
For the moment, I need consequitive numbers 1-200. In future iterations, I may need arbitrary lists of numbers, so I'm trying to keep the design flexible.
Perhaps there is a good LINQ solution? Any other ideas?

.NET 3,5 has Range too. It's actually Enumerable.Range and returns IEnumerable<int>.
The page you linked to is very much out of date - it's talking about 3 as a "future version" and the Enumerable static class was called Sequence at one point prior to release.
If you wanted to implement it yourself in C# 2 or later, it's easy - here's one:
IEnumerable<int> Range(int count)
{
for (int n = 0; n < count; n++)
yield return n;
}
You can easily write other methods that further filter lists:
IEnumerable<int> Double(IEnumerable<int> source)
{
foreach (int n in source)
yield return n * 2;
}
But as you have 3.5, you can use the extension methods in System.Linq.Enumerable to do this:
var evens = Enumerable.Range(0, someLimit).Select(n => n * 2);

var r = Enumerable.Range( 1, 200 );

Check out System.Linq.Enumerable.Range.
Regarding the second part of your question, what do you mean by "arbitrary lists"? If you can define a function from an int to the new values, you can use the result of Range with other LINQ methods:
var squares = from i in Enumerable.Range(1, 200)
select i * i;

Related

iterating with Linq

I am trying to find a way to access previous values from a Linq method in the same line.
I want to be able to use this general form in Linq:
var values = Enumerable.Range( 1, 100 ).Select( i => i + [last result] );
But I can't find a way to do something like this without multi-line lambda's and storing the results somewhere else.
So the best fibonacci sum I've been able to do in Linq is:
List<int> calculated = new List<int>( new int[] { 1, 2 });
var fibonacci = Enumerable.Range(2, 10).Select(i =>
{
int result = calculated[i - 2] + calculated[i - 1];
calculated.Add(result);
return result; // and how could I just put the result in fibonacci?
}
);
Which seems ugly. I could do this in less code with a regular for loop.
for (int i = 2; i < 10; i++)
{
calculated.Add(calculated[i - 2] + calculated[i - 1]);
}
It seems like if I could find a way to do this, I could use Linq to do a lot of Linear programming and sum a lot of iterative formulas.
If you are looking for a way to create a Fibonacci sequence generator, you would be better off writing your own generator function instead of using Linq extension methods. Something like this:
public static IEnumerable<int> Fibonacci()
{
int a = 1;
int b = 0;
int last;
for (;;) {
yield return a;
last = a;
a += b;
b = last;
}
}
Then you can apply Linq methods to this enumerable to achieve the result you want (try iterating over Fibonacci().Take(20) for example).
Linq extension methods are not the solution for every programming problem, and I can only imagine how horrid a pure LINQ Fibonacci sequence generator would look.
Closest you can come to something like that with LINQ is the IEnumerable.Aggregate method (a.k.a. fold from functional programming). You can use it to, for example, sum up the squares of a collection, like:
int sumSquares = list.Aggregate(0, (sum, item) => sum + item * item);
Since in LINQ the values are retrieved from a collection using an enumerator, i.e. they are taken one by one, by definition, there is no concept of "previous item". The items could even be generated and discarded on the fly, using some yield return magic. That said, you could always use some hack like:
long a= 1;
long b= 1;
var fibonacci = Enumerable.Range(1,20).Select(i => {
long last= a + b;
b = a;
a = last;
return last;
});
but the moment you have to use and modify an outside variable to make the lambdas work, you are in code-smell territory.

Project sequence so that each element will become sum of all before it with LINQ

I have a following code that transforms each element of an array into sum of all elements before it. The procedural implementation is as follows:
float[] items = {1, 5, 10, 100}; //for example
float[] sums = new float[items.Length];
float total = 0;
for(int i = 0; i < items.Length; i++){
total+=items[i];
sums[i] = total;
}
How would I implement this as a LINQ one-liner?
I know it can be done for example as
items.Select((x, i) => items.Take(i + 1).Sum())
but I think it's not very efficient when the array size grows, as it has to do Sum() for each element.
LINQ doesn't support this case very cleanly, to be honest - you want a mixture of aggregation and projection. You can do it with side-effects, which is horrible:
// Don't use this!
float sum = 0f;
var sums = items.Select(x => sum +=x).ToArray();
Side-effects in LINQ are nasty. Likewise you can do it using Take/Sum as shown by RePierre and L.B - but that takes an operation which is naturally O(N) and converts it into an operation which is O(N^2).
The MoreLINQ project I started a while ago does have support for this, in its Scan and PreScan members. In this case you want Scan, I believe:
var sums = items.Scan((x, y) => x + y);
If you don't want to use a third-party library, don't want to use side-effects, don't want the inefficiency of the Take solution, and only need addition, and only need it for a single type (e.g. float in your case) you can easily introduce your own method:
public static IEnumerable<float> RunningSum(this IEnumerable<float> source)
{
if (source == null)
{
throw new ArgumentNullException(source);
}
float sum = 0f;
foreach (var item in source)
{
sum += item;
yield return sum;
}
}
As you'll have noticed, this is basically the same code as your original - but is lazily evaluated and applies to any sequence of floats.
var result = items.Select((item, index) => items.Take(index).Sum() + item);
EDIT
You can use Aggregate method to create the sums:
var result = items.Aggregate(new List<float>(), (seed, item) =>
{
seed.Add(seed.LastOrDefault() + item);
return seed;
});
The Reactive Extensions team at Microsoft released an "Interactive Extensions" library that adds many useful extensions to IEnumerable<T>. One of them is Scan which does exactly what you want.
Here's the IX way of doing a running total:
IEnumerable<float> results = items.Scan(0.0f, (x1, x2) => x1 + x2);

How to define an array with equal value in c#?

I want to create a new array. Let's say
int[] clickNum = new int[800];
Then I want to do something like clickNum = 2, which would make all array elements starting from clickNum[0] to clickNum[800], set to 2. I know there's a way to do it by using a loop; but what I am after is just a function or a method to do it.
I suppose you could use Enumerable.Repeat when you initialise the array:
int[] clickNum = Enumerable.Repeat(2, 800).ToArray();
It will of course be slower, but unless you're going to be initiating literally millions of elements, it'll be fine.
A quick benchmark on my machine showed that initialising 1,000,000 elements using a for loop took 2ms, but using Enumerable.Repeat took 9ms.
This page suggests it could be up to 20x slower.
I don't think there's any built-in function to fill an existing array/list.
You could write a simple helper method for that if you need the operation in several places:
static void Fill<T>(IList<T> arrayOrList, T value)
{
for (int i = arrayOrList.Count - 1; i >= 0; i--)
{
arrayOrList[i] = value;
}
}
I guess you are looking for a function you created but you do not have the time to type it. So if you want it in a single line, try:
for(int i = 0; i < clickNum.Length; i++, clickNum[i] = 2);
Using Array.ConvertAll should be more efficient if you are working with very large arrays and performance is a concern:
int[] clickNum = Array.ConvertAll(new int[800], x => x = 2);
And you can also use a standard LINQ Select if performance doesn't worry you:
int[] clickNum = new int[800].Select(x => x = 2).ToArray();

Most efficient sorting algorithm for sorted sub-sequences

I have several sorted sequences of numbers of type long (ascending order) and want to generate one master sequence that contains all elements in the same order. I look for the most efficient sorting algorithm to solve this problem. I target C#, .Net 4.0 and thus also welcome ideas targeting parallelism.
Here is an example:
s1 = 1,2,3,5,7,13
s2 = 2,3,6
s3 = 4,5,6,7,8
resulting Sequence = 1,2,2,3,3,4,5,5,6,6,7,7,8,13
Edit: When there are two (or more) identical values then the order of those two (or more) does not matter.
Just merge the sequences. You do not have to sort them again.
There is no .NET Framework method that I know of to do a K-way merge. Typically, it's done with a priority queue (often a heap). It's not difficult to do, and it's quite efficient. Given K sorted lists, together holding N items, the complexity is O(N log K).
I show a simple binary heap class in my article A Generic Binary Heap Class. In Sorting a Large Text File, I walk through the creation of multiple sorted sub-files and using the heap to do the K-way merge. Given an hour (perhaps less) of study, and you can probably adapt that to use in your program.
You just have to merge your sequences like in a merge sort.
And this is parallelizable:
merge sequences (1 and 2 in 1/2), (3 and 4 in 3/4), …
merge sequences (1/2 and 3/4 in 1/2/3/4), (5/6 and 7/8 in 5/6/7/8), …
…
Here is the merge function :
int j = 0;
int k = 0;
for(int i = 0; i < size_merged_seq; i++)
{
if (j < size_seq1 && seq1[j] < seq2[k])
{
merged_seq[i] = seq1[j];
j++;
}
else
{
merged_seq[i] = seq2[k];
k++;
}
}
Easy way is to merge them with each other one by one. However, this will require O(n*k^2) time, where k is number of sequences and n is the average number of items in sequences. However, using divide and conquer approach you can lower this time to O(n*k*log k). The algorithm is as follows:
Divide k sequences to k/2 groups, each of 2 elements (and 1 groups of 1 element if k is odd).
Merge sequences in each group. Thus you will get k/2 new groups.
Repeat until you get single sequence.
UPDATE:
Turns out that with all the algorithms... It's still faster the simple way:
private static List<T> MergeSorted<T>(IEnumerable<IEnumerable<T>> sortedBunches)
{
var list = sortedBunches.SelectMany(bunch => bunch).ToList();
list.Sort();
return list;
}
And for legacy purposes...
Here is the final version by prioritizing:
private static IEnumerable<T> MergeSorted<T>(IEnumerable<IEnumerable<T>> sortedInts) where T : IComparable<T>
{
var enumerators = new List<IEnumerator<T>>(sortedInts.Select(ints => ints.GetEnumerator()).Where(e => e.MoveNext()));
enumerators.Sort((e1, e2) => e1.Current.CompareTo(e2.Current));
while (enumerators.Count > 1)
{
yield return enumerators[0].Current;
if (enumerators[0].MoveNext())
{
if (enumerators[0].Current.CompareTo(enumerators[1].Current) == 1)
{
var tmp = enumerators[0];
enumerators[0] = enumerators[1];
enumerators[1] = tmp;
}
}
else
{
enumerators.RemoveAt(0);
}
}
do
{
yield return enumerators[0].Current;
} while (enumerators[0].MoveNext());
}

Thoughts on foreach with Enumerable.Range vs traditional for loop

In C# 3.0, I'm liking this style:
// Write the numbers 1 thru 7
foreach (int index in Enumerable.Range( 1, 7 ))
{
Console.WriteLine(index);
}
over the traditional for loop:
// Write the numbers 1 thru 7
for (int index = 1; index <= 7; index++)
{
Console.WriteLine( index );
}
Assuming 'n' is small so performance is not an issue, does anyone object to the new style over the traditional style?
I find the latter's "minimum-to-maximum" format a lot clearer than Range's "minimum-count" style for this purpose. Also, I don't think it's really a good practice to make a change like this from the norm that is not faster, not shorter, not more familiar, and not obviously clearer.
That said, I'm not against the idea in general. If you came up to me with syntax that looked something like foreach (int x from 1 to 8) then I'd probably agree that that would be an improvement over a for loop. However, Enumerable.Range is pretty clunky.
This is just for fun. (I'd just use the standard "for (int i = 1; i <= 10; i++)" loop format myself.)
foreach (int i in 1.To(10))
{
Console.WriteLine(i); // 1,2,3,4,5,6,7,8,9,10
}
// ...
public static IEnumerable<int> To(this int from, int to)
{
if (from < to)
{
while (from <= to)
{
yield return from++;
}
}
else
{
while (from >= to)
{
yield return from--;
}
}
}
You could also add a Step extension method too:
foreach (int i in 5.To(-9).Step(2))
{
Console.WriteLine(i); // 5,3,1,-1,-3,-5,-7,-9
}
// ...
public static IEnumerable<T> Step<T>(this IEnumerable<T> source, int step)
{
if (step == 0)
{
throw new ArgumentOutOfRangeException("step", "Param cannot be zero.");
}
return source.Where((x, i) => (i % step) == 0);
}
In C# 6.0 with the use of
using static System.Linq.Enumerable;
you can simplify it to
foreach (var index in Range(1, 7))
{
Console.WriteLine(index);
}
You can actually do this in C# (by providing To and Do as extension methods on int and IEnumerable<T> respectively):
1.To(7).Do(Console.WriteLine);
SmallTalk forever!
I kind of like the idea. It's very much like Python. Here's my version in a few lines:
static class Extensions
{
public static IEnumerable<int> To(this int from, int to, int step = 1) {
if (step == 0)
throw new ArgumentOutOfRangeException("step", "step cannot be zero");
// stop if next `step` reaches or oversteps `to`, in either +/- direction
while (!(step > 0 ^ from < to) && from != to) {
yield return from;
from += step;
}
}
}
It works like Python's:
0.To(4) → [ 0, 1, 2, 3 ]
4.To(0) → [ 4, 3, 2, 1 ]
4.To(4) → [ ]
7.To(-3, -3) → [ 7, 4, 1, -2 ]
I think the foreach + Enumerable.Range is less error prone (you have less control and less ways to do it wrong, like decreasing the index inside the body so the loop would never end, etc.)
The readability problem is about the Range function semantics, that can change from one language to another (e.g if given just one parameter will it begin from 0 or 1, or is the end included or excluded or is the second parameter a count instead a end value).
About the performance, I think the compiler should be smart enough to optimize both loops so they execute at a similar speed, even with large ranges (I suppose that Range does not create a collection, but of course an iterator).
I think Range is useful for working with some range inline:
var squares = Enumerable.Range(1, 7).Select(i => i * i);
You can each over. Requires converting to list but keeps things compact when that's what you want.
Enumerable.Range(1, 7).ToList().ForEach(i => Console.WriteLine(i));
But other than for something like this, I'd use traditional for loop.
It seems like quite a long winded approach to a problem that's already solved. There's a whole state machine behind the Enumerable.Range that isn't really needed.
The traditional format is fundamental to development and familiar to all. I don't really see any advantage to your new style.
I'd like to have the syntax of some other languages like Python, Haskell, etc.
// Write the numbers 1 thru 7
foreach (int index in [1..7])
{
Console.WriteLine(index);
}
Fortunatly, we got F# now :)
As for C#, I'll have to stick with the Enumerable.Range method.
#Luke:
I reimplemented your To() extension method and used the Enumerable.Range() method to do it.
This way it comes out a little shorter and uses as much infrastructure given to us by .NET as possible:
public static IEnumerable<int> To(this int from, int to)
{
return from < to
? Enumerable.Range(from, to - from + 1)
: Enumerable.Range(to, from - to + 1).Reverse();
}
How to use a new syntax today
Because of this question I tried out some things to come up with a nice syntax without waiting for first-class language support. Here's what I have:
using static Enumerizer;
// prints: 0 1 2 3 4 5 6 7 8 9
foreach (int i in 0 <= i < 10)
Console.Write(i + " ");
Not the difference between <= and <.
I also created a proof of concept repository on GitHub with even more functionality (reversed iteration, custom step size).
A minimal and very limited implementation of the above loop would look something like like this:
public readonly struct Enumerizer
{
public static readonly Enumerizer i = default;
public Enumerizer(int start) =>
Start = start;
public readonly int Start;
public static Enumerizer operator <(int start, Enumerizer _) =>
new Enumerizer(start);
public static Enumerizer operator >(int _, Enumerizer __) =>
throw new NotImplementedException();
public static IEnumerable<int> operator <=(Enumerizer start, int end)
{
for (int i = start.Start; i < end; i++)
yield return i;
}
public static IEnumerable<int> operator >=(Enumerizer _, int __) =>
throw new NotImplementedException();
}
There is no significant performance difference between traditional iteration and range iteration, as Nick Chapsas pointed out in his excellent YouTube video. Even the benchmark showed there is some difference in nanoseconds for the small number of iterations. As the loop gets quite big, the difference is almost gone.
Here is an elegant way of iterating in a range loop from his content:
private static void Test()
{
foreach (var i in 1..5)
{
}
}
Using this extension:
public static class Extension
{
public static CustomIntEnumerator GetEnumerator(this Range range)
{
return new CustomIntEnumerator(range);
}
public static CustomIntEnumerator GetEnumerator(this int number)
{
return new CustomIntEnumerator(new Range(0, number));
}
}
public ref struct CustomIntEnumerator
{
private int _current;
private readonly int _end;
public CustomIntEnumerator(Range range)
{
if (range.End.IsFromEnd)
{
throw new NotSupportedException();
}
_current = range.Start.Value - 1;
_end = range.End.Value;
}
public int Current => _current;
public bool MoveNext()
{
_current++;
return _current <= _end;
}
}
Benchmark result:
I loved this way of implementation. But, the biggest issue with this approach is its inability to use it in the async method.
I'm sure everybody has their personal preferences (many would prefer the later just because it is familiar over almost all programming languages), but I am like you and starting to like the foreach more and more, especially now that you can define a range.
In my opinion the Enumerable.Range() way is more declarative. New and unfamiliar to people? Certainly. But I think this declarative approach yields the same benefits as most other LINQ-related language features.
I imagine there could be scenarios where Enumerable.Range(index, count) is clearer when dealing with expressions for the parameters, especially if some of the values in that expression are altered within the loop. In the case of for the expression would be evaluated based on the state after the current iteration, whereas Enumerable.Range() is evaluated up-front.
Other than that, I'd agree that sticking with for would normally be better (more familiar/readable to more people... readable is a very important value in code that needs to be maintained).
I agree that in many (or even most cases) foreach is much more readable than a standard for-loop when simply iterating over a collection. However, your choice of using Enumerable.Range(index, count) isn't a strong example of the value of foreach over for.
For a simple range starting from 1, Enumerable.Range(index, count) looks quite readable. However, if the range starts with a different index, it becomes less readable because you have to properly perform index + count - 1 to determine what the last element will be. For example…
// Write the numbers 2 thru 8
foreach (var index in Enumerable.Range( 2, 7 ))
{
Console.WriteLine(index);
}
In this case, I much prefer the second example.
// Write the numbers 2 thru 8
for (int index = 2; index <= 8; index++)
{
Console.WriteLine(index);
}
Strictly speaking, you misuse enumeration.
Enumerator provides the means to access all the objects in a container one-by-one, but it does not guarantee the order.
It is OK to use enumeration to find the biggest number in an array. If you are using it to find, say, first non-zero element, you are relying on the implementation detail you should not know about. In your example, the order seems to be important to you.
Edit: I am wrong. As Luke pointed out (see comments) it is safe to rely on the order when enumerating an array in C#. This is different from, for example, using "for in" for enumerating an array in Javascript .
I do like the foreach + Enumerable.Range approach and use it sometimes.
// does anyone object to the new style over the traditional style?
foreach (var index in Enumerable.Range(1, 7))
I object to the var abuse in your proposal. I appreciate var, but, damn, just write int in this case! ;-)
Just throwing my hat into the ring.
I define this...
namespace CustomRanges {
public record IntRange(int From, int Thru, int step = 1) : IEnumerable<int> {
public IEnumerator<int> GetEnumerator() {
for (var i = From; i <= Thru; i += step)
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
};
public static class Definitions {
public static IntRange FromTo(int from, int to, int step = 1)
=> new IntRange(from, to - 1, step);
public static IntRange FromThru(int from, int thru, int step = 1)
=> new IntRange(from, thru, step);
public static IntRange CountFrom(int from, int count)
=> new IntRange(from, from + count - 1);
public static IntRange Count(int count)
=> new IntRange(0, count);
// Add more to suit your needs. For instance, you could add in reversing ranges, etc.
}
}
Then anywhere I want to use it, I add this at the top of the file...
using static CustomRanges.Definitions;
And use it like this...
foreach(var index in FromTo(1, 4))
Debug.WriteLine(index);
// Prints 1, 2, 3
foreach(var index in FromThru(1, 4))
Debug.WriteLine(index);
// Prints 1, 2, 3, 4
foreach(var index in FromThru(2, 10, 2))
Debug.WriteLine(index);
// Prints 2, 4, 6, 8, 10
foreach(var index in CountFrom(7, 4))
Debug.WriteLine(index);
// Prints 7, 8, 9, 10
foreach(var index in Count(5))
Debug.WriteLine(index);
// Prints 0, 1, 2, 3, 4
foreach(var _ in Count(4))
Debug.WriteLine("A");
// Prints A, A, A, A
The nice thing about this approach is by the names, you know exactly if the end is included or not.

Categories

Resources