-3

I have a list of names, and I want to implement a custom ordering by implementing the IComparer<T> interface. This custom sort must check the first names of two items, and if they are the same, it should group them together. For example, the final result should be:

John       Locke
John       Doe
Elizabeth  Davis
Elizabeth  Hurley
Ashley     Williams

I do not want to change the ordering of the list by first name. I just want to group together items with the same first name, but different last names.

class Program
{
    static void Main(string[] args)
    {
        List<Name> names = new List<Name>
        {
            new Name {FirstName = "John", LastName = "Locke"},
            new Name {FirstName = "Elizabeth", LastName = "Davis"},
            new Name {FirstName = "John", LastName = "Doe"},
            new Name {FirstName = "Ashley", LastName = "Williams"},
            new Name {FirstName = "Elizabeth", LastName = "Hurley"}
        };

        foreach (Name name in names)
        {
            Console.WriteLine($"{name.FirstName, -10} {name.LastName, -10}");
        }

        Console.WriteLine("\n\n");

        List<Name> sorted = names.OrderBy(o => o, new NameComparer()).ToList();

        foreach (Name name in sorted)
        {
            Console.WriteLine($"{name.FirstName,-10} {name.LastName,-10}");
        }

        Console.ReadKey();
    }
}

public sealed class Name
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

public sealed class NameComparer : IComparer<Name>
{
    public int Compare(Name x, Name y)
    {
    }
}
Vahid
  • 5,144
  • 13
  • 70
  • 146
  • And what it the issue do you have with this code? – Pavel Anikhouski May 27 '20 at 16:03
  • @PavelAnikhouski I do not know how to actually do it inside Compare(). – Vahid May 27 '20 at 16:06
  • What's wrong with a simple `names.OrderBy(x => x.FirstName).ThenBy(x => x.LastName).ToList();`? – George Kerwood May 27 '20 at 16:06
  • @GeorgeKerwood I do not want the touch the ordering of the list by FirstName, I just want to bring together the ones with similar FirstName but different LastName. – Vahid May 27 '20 at 16:07
  • 1
    @Vahid, I'm sorry, I clearly haven't understood what you mean by "bring together". Kindly clarify. – George Kerwood May 27 '20 at 16:09
  • @GeorgeKerwood The first item is John Lock, then we look in the list, and see that John Doe also starts with John, so we bring it after John Locke, the next item is now Elizabeth Davis, we look and bring Elizabeth Hurley next to it, and so on. – Vahid May 27 '20 at 16:12
  • @Vahid That's what a sort is... a change in order. Looking again at your desired output, you do not want to produce a list that is alphabetically sorted by first name, only group first names in some "natural" order? May I ask why? – George Kerwood May 27 '20 at 16:13
  • @GeorgeKerwood Thank you George, I do not take them seriously :) I actually knew that I may need a custom algorithm to extract these, but since I had not used IComparer before, I thought I give it a try by asking maybe I was missing something I thought. – Vahid May 27 '20 at 16:31
  • 1
    @Vahid, Open the question again, I've done it with `IComparer` :) – George Kerwood May 27 '20 at 16:41
  • @GeorgeKerwood I voted to reopen. – Vahid May 27 '20 at 16:42
  • @Vahid, ah never mind, here: `return x.FirstName == y.FirstName ? 0 : -1;` That's all you need in the `Compare(Name x, Name y)` – George Kerwood May 27 '20 at 16:45
  • It can only move elements up, but will do so until they group. Not perfect to your desired output, but will be the minimum shifts to group `FirstName`. – George Kerwood May 27 '20 at 16:46
  • @GeorgeKerwood Thank you George, I really appreciate the effort. – Vahid May 27 '20 at 16:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/214758/discussion-between-george-kerwood-and-vahid). – George Kerwood May 27 '20 at 16:48

2 Answers2

-1

As per documentation

  • If result is less than 0, then first argument is less than second,
  • If result is 0, then arguments is of same order,
  • Else, second is less than first

Thus, if you don't need to order items with same LastName, you can just compare FirstName using default string comparison:

public sealed class NameComparer : IComparer<Name>
{
    public int Compare(Name x, Name y)
    {
        return x.FirstName.CompareTo(y.FirstName);
    }
}
-2

A simple dictionary sort on the first name should suffice given your requirements:

public sealed class NameComparer : IComparer<Name>
{
    public int Compare(Name x, Name y) => x.FirstName.CompareTo(y.FirstName);
}
Blindy
  • 65,249
  • 10
  • 91
  • 131
  • Hi Blindy, I do not want to disturb the general order of the list, just bring the ones with the same FirstName closer. – Vahid May 27 '20 at 16:10
  • @Vahid This "bring together"/"bring closer" has everyone confused, my friend. Especially since your question title asks regarding "sort". By definition a sort is a change in order. – George Kerwood May 27 '20 at 16:13
  • @GeorgeKerwood I agree, I could not find the right wording for this. – Vahid May 27 '20 at 16:15
  • @GeorgeKerwood What I have in mind is that the list has a order at first, I want to order it in a way that the items with similar first names are clustered together. – Vahid May 27 '20 at 16:17
  • "I want to order it in a way that the items with similar first names are clustered together." that's exactly what both answers so far have given you, and what you'll most likely get until someone just closes your question for being malformed, regardless of your downvotes. – Blindy May 27 '20 at 16:19
  • No, your solution does not what I have in mind! ,) – Vahid May 27 '20 at 16:35
  • But it does what you *said*. – Blindy May 27 '20 at 16:37