patterncsharpMinor
Is there an easier way to use Rx's GroupBy operator?
Viewed 0 times
useoperatorwaygroupbythereeasier
Problem
I'm just playing with the concept of
Here is what I have:
Result
GroupBy inside Rx. So, I wondered how hard it would be to write a console application that continuously reads lines, groups them by similar words and just prints out the word among the current count of how often the word was written before. It really was a breeze to do that but I wonder if my attempt could be rewritten in a more elegant way. Especially if I can get rid of the nested Subscribes.Here is what I have:
static void Main(string[] args)
{
var subject = new Subject();
var my = subject.GroupBy(x => x);
my.Subscribe(x => x.Scan(new { Chars = string.Empty, Count = 0},
(a, chars) => new { Chars = chars, Count = a.Count + 1})
.Subscribe(result => Console.WriteLine("You typed {0} {1} times", result.Chars,
result.Count)));
while (true)
{
subject.OnNext(Console.ReadLine());
}
}Result
test
you typed test 1 times
test
you typed test 2 times
hallo
you typed test 1 times
test
you typed test 3 times
...Solution
You could use also use a counter provider per grouping observable, in the form of zipping a large stream of integers, like so:
static void Main(string[] args)
{
var input = GetConsoleLines().ToObservable().TakeWhile(line => !string.IsNullOrEmpty(line));
input.GroupBy(word => word)
.SelectMany(grouping => grouping.Zip(Observable.Range(1, int.MaxValue), (s, i) => new Tuple(s, i)))
.Subscribe(r => Console.WriteLine($"you typed {r.Item1} {r.Item2} times"));
}
public static IEnumerable GetConsoleLines()
{
while(true)
yield return Console.ReadLine();
}Code Snippets
static void Main(string[] args)
{
var input = GetConsoleLines().ToObservable().TakeWhile(line => !string.IsNullOrEmpty(line));
input.GroupBy(word => word)
.SelectMany(grouping => grouping.Zip(Observable.Range(1, int.MaxValue), (s, i) => new Tuple<string, int>(s, i)))
.Subscribe(r => Console.WriteLine($"you typed {r.Item1} {r.Item2} times"));
}
public static IEnumerable<string> GetConsoleLines()
{
while(true)
yield return Console.ReadLine();
}Context
StackExchange Code Review Q#5989, answer score: 2
Revisions (0)
No revisions yet.