3

I have below code -

var refNosToOrder = new int[9] {1,2,3,4,5,6,7,8,9}

var orderedList = lst.OrderBy(x=>x.RefNo==7)
                     .ThenBy(y=> refNosToOrder.Contains(y.RefNo)).ToList();

lst is list of class object containing int property - RefNo : i.e. List<SampleClass>

class SampleClass
{
  public int RefNo {get;set;}
}

lst contains all the unsorted data of RefNo:

lst = 2,4,6,9,7,5,8,1,3

What I want to do -

First I want to order lst by keeping first element as - 7; then for the rest of the list, it should be ordered as the array refNosToOrder

i.e. Final output I am expecting to be -

7,1,2,3,4,5,6,8,9

With the above code -

var orderedList = lst.OrderBy(x=>x.RefNo==7)
                         .ThenBy(y=> refNosToOrder.Contains(y.RefNo)).ToList();

It is giving - 2,4,6,9,7,5,8,1,3 i.e. this code is not at all ordering the list.

6
  • 1
    Shouldn't your ThenBy() contain somethin like ThenBy(y => y.RefNo) ? Look at this post where I saw that Commented Dec 14, 2021 at 13:34
  • No .. Rest of the RefNo should get ordered by refNosToOrder array @Error404Brainnotfound Commented Dec 14, 2021 at 13:36
  • Oh my bad, i didn't understand that part of the question! Commented Dec 14, 2021 at 13:37
  • So what if refNosToOrder is 6, 6, 6, 6? Would you want four copies of the original? Is refNosToOrder always going to be (effectively) a number followed by a linear sequence that doesn't have that number? Commented Dec 14, 2021 at 13:38
  • refNosToOrder will always have unique elements in it. I dont want to have copies. @JeroenMostert Commented Dec 14, 2021 at 13:39

1 Answer 1

5

Contains returns a boolean of whether an element is in a list or not, which won't be very helpful here. Instead, you could sort by the index of that element:

var orderedList = 
    lst.OrderBy(x => x.RefNo != 7)
       .ThenBy(y => Array.IndexOf(refNosToOrder, y.RefNo))
       .ToList();

EDIT:
Following up on Jeroen Mostert's comment, this sorting has quadratic complexity. For large refNosToOrder it may be more efficient to first convert the array to a dictionary of orders and then use it for the sorting:

var orderDict = 
    Enumerable.Range(0, refNosToOrder.Length).ToDictionary(i => refNosToOrder[i]);
var orderedList = 
    lst.OrderBy(x => x.RefNo != 7).ThenBy(y => orderDict[y.RefNo]).ToList();
Sign up to request clarification or add additional context in comments.

3 Comments

Do note that this solution has quadratic performance due to the repeated linear search in refNosToOrder -- OK if your arrays are 10 elements, no longer OK if they're 10 000 elements. At that point creating lookups first starts to make sense.
@JeroenMostert good point, thanks! Edited that in to the answer (with the appropriate credit, of course)
@Mureinik - If lst contains elements outside the refNosToOrder - then it is giving preference to those numbers after 7. Eg. if lst contains - 2,4,6,9,7,5,8,1,3 and refNosToOrder = 3,4,5 then it is outputing as - 7,1,2,3,4,5,6,8,9 ; where it should have been - 7,3,4,5,1,2,6,8,9

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.