1

I can not seem to figure out how I could order a set of data big, small, big small.

Suppose I have:

32.00
95.00
60.00
14.00
62.00

The grouping would end up:

95 and 62
60 and 32
14 all by himself

I can stick it in a datatable but even then...not entirely sure how I would get the results desired.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
losrob
  • 115
  • 1
  • 7

2 Answers2

1

Another way is to use Enumerator and write a custom LINQ extensions method.
This method is more efficient because it eliminates multiple enumeration of collection:

public static class LinqExtensions
{
    public static IEnumerable<Tuple<T, T>> GroupBy2<T>(this IEnumerable<T> source)
    {
        var enumerator = source.GetEnumerator();
        try
        {
            while (enumerator.MoveNext())
            {
                T first = enumerator.Current;

                if (!enumerator.MoveNext()) {
                    yield return new Tuple<T, T>(first, default(T));
                    yield break;
                }

                T second = enumerator.Current;

                yield return new Tuple<T, T>(first, second);
            }
        }
        finally
        {
            if (enumerator != null)
                enumerator.Dispose();
        }
    }
}

Usage example:

var data = new List<double>() { 32.00, 95.00, 60.00, 14.00, 62.00 };

// As Tuple<double, double>[] array:
var results = data.OrderByDescending(x => x).GroupBy2().ToArray(); 

// Iterate through IEnumerable<Tuple<double, double>>:
foreach (var pair in data.OrderByDescending(x => x).GroupBy2())
{
    Console.WriteLine($"{pair.Item1} {pair.Item2}");
}

Result:

32 95
60 14
62 0

You can provide another behaviour instead of default(T) for non-even item.
For example, this implementation returns null as the second tuple item if pair does not exist, but it doens't work for classes.

public static IEnumerable<Tuple<T, T?>> GroupBy2<T>(this IEnumerable<T> source) 
    where T : struct
{
    var enumerator = source.GetEnumerator();
    try
    {
        while (enumerator.MoveNext())
        {
            T first = enumerator.Current;

            if (!enumerator.MoveNext()) {
                yield return new Tuple<T, T?>(first, null);
                yield break;
            }

            T second = enumerator.Current;

            yield return new Tuple<T, T?>(first, second);
        }
    }
    finally
    {
        if (enumerator != null)
            enumerator.Dispose();
    }
}
Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
0

The below code puts the entries in order, then marries up the odd entries (first, third etc) with the even entries (second, fourth etc) with Zip.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
    public class Program
    {
        static void Main(string[] args)
        {
            var data = new List<double>() {32.00, 95.00, 60.00, 14.00, 62.00};

            var ordered = data.OrderByDescending(z => z);
            var oddGrouped = ordered.Select((value, index) =>
                new {value, index}).Where(z => z.index % 2 == 0).Select(z => z.value);
            var evenGrouped = ordered.Select((value, index) =>
                new { value, index }).Where(z => z.index % 2 == 1).Select(z => (int?)z.value)
                .Concat(new List<int?>() { null}  ); // extra entry at the end in case there are an odd number of elements

            var result = oddGrouped.Zip(evenGrouped, (odd, even) => new Tuple<double, double?>(odd, even)).ToList();

            foreach (var entry in result)
            {
                Console.WriteLine(entry);
            }

            Console.ReadLine();
        }
    }
}
mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Could you help me understand what oddGrouped.Zip is doing? please...Just tested your code and it works wonderfully! Thanks! – losrob Jun 29 '17 at 03:33
  • @losrob Check out https://stackoverflow.com/questions/5122737/what-is-the-use-of-enumerable-zip-extension-method-in-linq . – mjwills Jun 29 '17 at 04:09
  • Ah! understood...now it makes sense. Super useful! Did not know this existed. Thanks!!! – losrob Jun 29 '17 at 04:50