Let's imagine we have a list of strings var listA = new List<string> {"B", "C", "A"}, and it is sorted in the desired manner.
And, there is an object defined like:
public class Sample {
public string Letter {get;set;} // "A","B","C","D","#"
public string Number {get;set;} // not relevant
}
Also, there is another list, List<Sample> listB, and I want to sort it in a way that first comes objects with Letter values "B", then "C" and on the end, "A", so to respect same order as it is in the listA. Any ideas? :)
EDIT: Letter property can have a wider range of characters, unlike listA which can have just those 3. Expected order "B","C", "A"..."all the rest, order not relevant"
Assume value of Letter are within listA. It's worth considering redesigning the algorithm if the assumption is false. And it may depend on requirement of expected order the out of range ones.
var sortedSamples = listB.OrderBy(x=>listA.IndexOf(x.Letter));
For better performance, cache the orders into a dictionary:
var orders = new Dictionary<string, int>();
for (int i = 0; i < listA.Count; i++)
{
orders.Add(listA[i], i);
}
var sortedSamples = listB.OrderBy(x=>orders[x.Letter]);
If possible values range of Letter is much smaller than listA, then better consturct orders like this:
foreach (string letter in listB.Select(x=>x.Letter))
{
orders.Add(letter, listA.IndexOf(letter));
}
Update
If letters' range are out of listA, and since OP want the out ones to be at the end:
var orders = new Dictionary<string, int>();
for (int i = 0; i < listA.Count; i++)
{
orders.Add(listA[i], i);
}
int lastIndex = listA.Count;
foreach (string letter in listB.Select(x=>x.Letter)
.Distinct().Except(listA))
{
orders.Add(letter, lastIndex);
}
You should using something like this
var listA = new List<string> { "B", "C", "A" };
var listB = new List<string> { "A", "B", "C" };
listB = listB.OrderBy(d => listA.IndexOf(d)).ToList();
// listB: "B", "C", "A"
You could use this extension which also supports comparing the entries in the lists by a specific property (e.g. id instead of reference)
public static IEnumerable<TFirst> OrderBy<TFirst, TSecond, TKey>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TKey> firstKeySelector, Func<TSecond, TKey> secondKeySelector) =>
second
.Join(
first,
secondKeySelector,
firstKeySelector,
(_, firstItem) => firstItem);
this will sort the items in second the same way as they are already sorted in first comparing them using both key selectors.
Be aware that this only works if ALL the keys in first are also present in second.