7 Replies - 1092 Views - Last Post: 05 August 2016 - 02:21 PM

#1 andrewsw  Icon User is offline

  • say what now
  • member icon

Reputation: 6409
  • View blog
  • Posts: 25,904
  • Joined: 12-December 12

LINQ Playground

Posted 04 August 2016 - 11:49 AM

This topic (and others) encouraged me to play around with LINQ and the Enumerable.Range method. I was encouraged by finding this expression:
char[] alphabet = Enumerable.Range('A', 26).Select(x => (char)x).ToArray();

noting that a character can provide the initial (integer) value. I pursued this a little as I, firstly, wanted to create a dictionary populated by the letters of the alphabet as keys with default values of 0:
        Dictionary<char, int> alpha = Enumerable.Range('A', 26).Select(x => (char)x)
            .ToDictionary(x => x, x => 0);

        foreach (var item in alpha) {
            Console.WriteLine("{0} : {1}", item.Key, item.Value);   
        }

I then pursued my idea a little further to also obtain a tally of the occurrences of letters in a string, with zeroes for missing letters:
        string sample = "hello there Bob".ToUpper();

        Dictionary<char, int> alpha = Enumerable.Range('A', 26).Select(x => (char)x)
            .ToDictionary(x => x, x => sample.Count(c => c == x));

        foreach (var item in alpha) {
            Console.WriteLine("{0} : {1}", item.Key, item.Value);   
        }

Do you have an interesting example of LINQ to post and discuss? Perhaps we should concentrate on examples using Range to give the topic some focus, although I am also intrigued by the possibility of creating custom enumerable methods (an idea that occurred was for a custom version of Range that allows a step argument).

Anyway, a few interesting LINQ examples are encouraged ;).



Of course, if your example is generally useful then you could consider posting it in the Snippets section (if it isn't too brief/trivial).

Is This A Good Question/Topic? 2
  • +

Replies To: LINQ Playground

#2 Curtis Rutland  Icon User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5101
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: LINQ Playground

Posted 04 August 2016 - 12:36 PM

I know I've mentioned this before, but if anyone wants a very easy environment to play around with LINQ (or any other C# code), search for "LINQPad". The free version is great, the paid ones are even better.

That aside, @Andy, I like that you mentioned adding extension methods to IEnumerable. I've been making use of that myself, and I will share a few of my favorites that I've re-used.

First is Each. For some reason, MS added .ForEach as a method to List<T>, but not to IEnumerable. So I did. I also allowed you to decide whether that would execute in parallel or not.

public static void Each<T>(this IEnumerable<T> collection, Action<T> action, bool parallel = false)
{
	if(parallel) Parallel.ForEach(collection, action);
	else foreach(var item in collection) action(item);
}



Here's an example using it (actually your own example, modified slightly):

var sample = "hello there Bob".ToUpper();
var alphas = Enumerable.Range('A', 26).Select(a => (char)a).ToArray();
var letterCounts = alphas.Select(a => new { Letter = a, Count = sample.Count(c => c == a)});
letterCounts.Each(l => Console.WriteLine($"{l.Letter}:{l.Count}"));



I like this because it takes advantage of anonymous types. They're great, they're the closest thing to a native Tuple that C# offers (can't wait for C# 7 w/ Native Tuples).

Here's another extension method I've used several times. It's not perfect, but I like it. It takes a collection and makes it into a collection of collections, with elements being no larger than the provided "chunkSize". So, if you wanted to take a list of 50 items and show them in rows of four columns, you would use this method:

public static IEnumerable<IEnumerable<T>> Segment<T>(this IEnumerable<T> collection, int chunkSize)
{
	if (chunkSize < 1) yield break;
	var queue = new Queue<T>(collection);
	while (queue.Count > 0)
	{
		var output = new List<T>();
		for (var i = 0; i < chunkSize; i++)
		{
			if (queue.Count == 0)
			{
				if (output.Count > 0)
					yield return output;
				yield break;
			}
			output.Add(queue.Dequeue());
		}
		yield return output;
	}
}



Usage would be like this:

var segmentedCollection  = collection.Segment(4);
foreach(var subCollection in segmentedCollection) {
  //do something for rows
  foreach(var item in subCollection) {
    //do something for columns
  }
}

Was This Post Helpful? 2
  • +
  • -

#3 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: LINQ Playground

Posted 04 August 2016 - 01:07 PM

View PostCurtis Rutland, on 04 August 2016 - 09:36 PM, said:

Here's another extension method I've used several times. It's not perfect, but I like it. It takes a collection and makes it into a collection of collections, with elements being no larger than the provided "chunkSize".


Here's a version that should also work with infinite enumerables:

public static IEnumerable<IEnumerable<T>> Segment<T>(this IEnumerable<T> collection, int chunkSize)
{
    while(collection.Any())
    {
        yield return collection.Take(chunkSize);
        collection = collection.Skip(chunkSize);
    }
}



It's untested though, as I don't have a C# compiler handy to test right now. So please point out any errors. I tested it and it appears to work fine.

This post has been edited by sepp2k: 05 August 2016 - 12:41 PM

Was This Post Helpful? 2
  • +
  • -

#4 andrewsw  Icon User is offline

  • say what now
  • member icon

Reputation: 6409
  • View blog
  • Posts: 25,904
  • Joined: 12-December 12

Re: LINQ Playground

Posted 05 August 2016 - 01:16 PM

I suppose the simplest version of an infinite enumerable is this:
IEnumerable<int> Infinite() {
    int i = 1;
    while (true)
        yield return i++;
}

On execution, though, it only runs infinitely (if allowed to) because the default behaviour for an overflowing int is to resume from negative numbers. But its definition presents an acceptable definition of an infinite enumerable. (It's not mine anyway, from here.)

I needed to modify it though, as I don't have infinite time available:
        static IEnumerable<int> Infinite() {
            int i = 1;
            while (true) {
                if (i < 1000)
                    yield return i;
                else
                    yield break;
                i++;
            }
        }

To be able to test this with the previous code we should first place the definition for Segment in a separate static class; I've placed it within the same namespace:
namespace ConsoleApplication3 {
    public static class Extensions {
        public static IEnumerable<IEnumerable<T>> Segment<T>(this IEnumerable<T> collection, int chunkSize) {
            while (collection.Any()) {
                yield return collection.Take(chunkSize);
                collection = collection.Skip(chunkSize);
            }
        }
    }
}

The we can test Segment like this:
namespace ConsoleApplication3 {

    class Program {
        static void Main(string[] args) {

            IEnumerable<int> lots = Infinite();

            var chunk = lots.Segment(5);
            foreach (var block in chunk) {
                foreach (var item in block) {
                    Console.Write("{0}, ", item);
                }
                Console.WriteLine();
            }
            Console.ReadKey();
        }
    }
}


View Postsepp2k, on 04 August 2016 - 08:07 PM, said:

It's untested though, as I don't have a C# compiler handy to test right now. So please point out any errors. I tested it and it appears to work fine.

I could have waited a bit longer ;)
Was This Post Helpful? 0
  • +
  • -

#5 andrewsw  Icon User is offline

  • say what now
  • member icon

Reputation: 6409
  • View blog
  • Posts: 25,904
  • Joined: 12-December 12

Re: LINQ Playground

Posted 05 August 2016 - 01:24 PM

Off topic: I suppose as we can define infinite enumerables and can supply functions as arguments there is a lot of scope for doing clever things with mathematical series, such as finding approximations and supplying deltas for termination (and, again, using Range). This is a little outside my comfort zone though, but I'm speculating that such is possible?

Perhaps we shouldn't pursue this too far here, though, a little too off topic ;)
Was This Post Helpful? 0
  • +
  • -

#6 Curtis Rutland  Icon User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5101
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: LINQ Playground

Posted 05 August 2016 - 01:58 PM

View Postandrewsw, on 05 August 2016 - 03:16 PM, said:

I suppose the simplest version of an infinite enumerable is this:
IEnumerable<int> Infinite() {
    int i = 1;
    while (true)
        yield return i++;
}


If you want to get technical, I'd probably consider this to be the most "simple" infinite enumerable:

IEnumerable<bool> Infinite() { while (true) yield return true; }

Was This Post Helpful? 0
  • +
  • -

#7 andrewsw  Icon User is offline

  • say what now
  • member icon

Reputation: 6409
  • View blog
  • Posts: 25,904
  • Joined: 12-December 12

Re: LINQ Playground

Posted 05 August 2016 - 02:06 PM

I could go 1 better
static IEnumerable<int> TheOne() { while (true) yield return 1; }

but let's not get technical ;)
Was This Post Helpful? 0
  • +
  • -

#8 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Re: LINQ Playground

Posted 05 August 2016 - 02:21 PM

RX's Observable.Never is probable the "simplest".
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1