Search code examples
c#arraysalgorithmsortingemail-address

Interleave an array of email addresses avoiding items with same domain to be consecutive


I'm looking for an efficient way of sorting an array of email addresses to avoid items with the same domain to be consecutive, in C#.

Email addresses inside the array are already distinct and all of them are lower case.

Example:

Given an array with the following entries:

[email protected]
[email protected]
[email protected]
[email protected]

I would like to obtain something similar to the following:

[email protected]    
[email protected]
[email protected]
[email protected]

Solution

  • With the help of an extension method (stolen from https://stackoverflow.com/a/27533369/172769), you can go like this:

    List<string> emails = new List<string>();
    emails.Add("[email protected]");
    emails.Add("[email protected]");
    emails.Add("[email protected]");
    emails.Add("[email protected]");
    
    var q = emails.GroupBy(m => m.Split('@')[1]).Select(g => new List<string>(g)).Interleave();
    

    The Interleave method is defined as:

    public static IEnumerable<T> Interleave<T>(this IEnumerable<IEnumerable<T>> source )
    {
        var queues = source.Select(x => new Queue<T>(x)).ToList();
        while (queues.Any(x => x.Any())) {
            foreach (var queue in queues.Where(x => x.Any())) {
                yield return queue.Dequeue();
            }
        }
    }
    

    So basically, we create groups based on the domain part of the email adresses, project (or Select) each group into a List<string>, and then "Interleave" those lists.

    I have tested against your sample data, but more thorough testing might be needed to find edge cases.

    DotNetFiddle snippet

    Cheers