Search code examples
c#sortingicomparer

How can I use an IComparer<T> to sort by arbitrary values?


I receive a sorted list of integers which I would like to use to sort a ListCollectionView via ListCollectionView.CustomSort. This property accepts an IComparer and I've created one but, as expected, I can only compare values on generic objects x and y.

public List<int> SortedIds = new List<int> { 13, 7, 5, 3, 1 };
public class Item {
  int Id { get; set; }    
}

public class IdComparer : IComparer<Item> {
  public int Compare(Item x, Item y) {
    // Comparisons 
    // ???
    // return 0;
  }
}

Solution

  • If you want to compare by their index in your SortedIds list, you can do:

    public class IdComparer : IComparer<Item> {
        private readonly Dictionary<int, int> idIndexes;
        public IdComparer(IEnumerable<int> sortedIds)
        {
            idIndexes = sortedIds
                .Select((id, idx) => new { Id = id, Index = idx })
                .ToDictionary(p => p.Id, p.Index);
        }
    
        public int Compare(Item x, Item y) {
            xIndex = idIndexes[x.Id];
            yIndex = idIndexes[y.Id]
            return xIndex.CompareTo(yIndex);
        }
    }
    

    However you could use linq:

    IEnumerable<Item> sorted = SortedIds
        .Select((id, idx) => new { Id = id, Index = idx })
        .Join(items, p => i.Id, item => item.Id, (p, item) => new { Item = item, Index = idx })
        .OrderBy(p => p.Index)
        .Select(p => p.Item);