5

I have a list of strings that I want to sort by another list of strings and if there are items in the list that is not in the comparer list I want them as they are at the end of the list. How can I do this?

So if I have this list: List<string> {"A","T","G","F","V","E","W","Q" }
and I have a comparer: List<string> {"T","F","V","A" }
I want the result to be: List<string> {"T","F","V","A","G","E","W","Q" }

Thanks!

Johan Ketels
  • 167
  • 1
  • 9

4 Answers4

9

It looks like you need to use Intersect and Except like:

List<string> originalList = new List<string> {"A", "T", "G", "F", "V", "E", "W", "Q"};
List<string> compareList = new List<string> {"T", "F", "V", "A"};

var intersectedItems = compareList.Intersect(originalList);
var notIntersectedItems = originalList.Except(compareList);
var resultList = intersectedItems.Concat(notIntersectedItems).ToList();

You will get:

resultList = T,F,V,A,G,E,W,Q
Habib
  • 219,104
  • 29
  • 407
  • 436
6

You can use List<T>.IndexOf and use int.Maxvalue if it returns -1:

List<string> result = list.OrderBy(str => {
    int index = comparer.IndexOf(str);
    return index == -1 ? int.MaxValue : index;
}).ToList();

Here is a long version which might be more readable for some. It's also more flexible since you can specify what happens with the not-contained items. You could for example order them lexicographically by adding ThenBy(x => x.String) before Select(x => x.String):

List<string> result = list.Select(str => new
    {
        ComparerIndex = comparer.IndexOf(str),
        String = str
    })
    .OrderBy(x => x.ComparerIndex == -1 ? 1 : 0) // not contained -> at the end
    .ThenBy(x => x.ComparerIndex)
    .Select(x => x.String)
    .ToList();
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
2

This should do it:

var a = new List<string> {"A","T","G","F","V","E","W","Q" };
var b = new List<string> {"T","F","V","A"};

var res = b.Concat(a.Except(b));
Magnus
  • 45,362
  • 8
  • 80
  • 118
  • 2
    I prefer this answer to the others because it is more readable, to me at least. Although the others are very good also. – Mr. Mr. Feb 26 '15 at 14:01
  • 1
    I don't think this answers the question asked, this answer gives you all the elements in b but i believe the question is asking for the elements of a that are contained within b to be at the start of the new list. In other words b could have elements not present in a, and b is just the sorting element – theDarse Feb 26 '15 at 14:05
0
List<string> input = new List<string> { "A", "T", "G", "F", "V", "E", "W", "Q" };
List<string> input1 = new List<string> { "T", "F", "V", "A" };
var res = input.Union(input1).OrderBy(c => c).ToList();
Lokesh B R
  • 272
  • 1
  • 8