-1

I want to sort List on the basis of CityName such that records with CityName Lahore appears first then Islamabad and then Karachi. Below is the source code for reference,

class Address {
private City;
}
class City{
private CityName;
}

I am looking for a way to do it with the LINQ OrderBy method.

uinvent
  • 25
  • 8

2 Answers2

4

You can use List.IndexOf:

IEnumerable<string> query = cityList.OrderBy(orderedCityList.IndexOf);

If a string is not contained in the order-list IndexOf returns -1so these cities will be first. If you want them to be at the end of the list you can use this query:

IEnumerable<string> query = cityList
    .Select(s => new { City = s, Index = orderedCityList.IndexOf(s) })
    .OrderBy(x => x.Index >= 0 ? x.Index : int.MaxValue)
    .Select(x => x.City);
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • What if cityList is part of an object? than I believe it will not be useful. – uinvent May 03 '18 at 10:02
  • 1
    @UmairKhan: what do you mean by that? If it's not a `List` but a `List` and the string is actually a property in that class: `cityList.OrderBy(c=> orderedCityList.IndexOf(c.CityName))` – Tim Schmelter May 03 '18 at 10:03
  • 1
    _What if cityList is part of an object?_ that was not part of the question – fubo May 03 '18 at 10:05
  • @TimSchmelter Yes it is a List and this List is also part of another object. Thus IndexOf method will not be helpful. – uinvent May 03 '18 at 10:21
  • 1
    @UmairKhan: well, why you don't ask the right question then? Why you let us find a solution for a non.existing problem? Also, do you want to re-order this single list or is this `City`-object part of another collection that you want to order? Not clear at all. – Tim Schmelter May 03 '18 at 10:28
  • @UmairKhan: have you read my comment above? Was this not helpful? `cityList.OrderBy(c=> orderedCityList.IndexOf(c.CityName))`. It's not even cleat what type the list has that you want to order. – Tim Schmelter May 03 '18 at 10:46
  • @TimSchmelter First of all thanks for your time. I have updated my question, which shows code structure too. I didn't get the source of orderedCityList. Do you mean that I need to create a separate list first e.g. `List orderedCityList = new List() { "Lahore", "Islamabad", "Karachi", }; ` – uinvent May 03 '18 at 12:05
  • @UmairKhan: yes exactly, i thought you had already such a list (or array). – Tim Schmelter May 03 '18 at 12:13
2

I suggest mapping (i.e. map actual city name to the desired order):

  Dictionary<string, int> order = new Dictionary<string, int> {
    {"Lahore", 1}, 
    {"Islamabad", 2}, 
    {"Karachi", 3},
  };


  ...

  var result = myCollection
    .OrderBy(city => order[city]);

In case you have arbitrary cities in the myCollection and want first have Lahore, Islamabad, Karachi (in this order) and then all the other cities:

  var result = myCollection
    .OrderBy(city => order.TryGetValue(item, out var map) ? map : int.MaxValue)
    .ThenBy(city => city);

Edit: Why Dictionary? Dictionary is efficient in general case, esp. if you have a long list of cities. To turn a list into the dictionary:

  List<string> cities = new List<string>() {
    "Lahore",
    "Islamabad",
    "Karachi",     
  };  

  Dictionary<string, int> order = cities 
    .Select((value, index) => new {value = value, index = index})    
    .ToDictionary(item => item.value, item => item.index);

However, If you have a guarantee that it'll be just few (say, 3) exceptional cities my solution is an overkill and Tim Schmelter's one is better.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 3
    Why create the dictionary when you can just make a list like Tim suggests? – adjan May 03 '18 at 09:55
  • 1
    @Adrian: If list is *short* (as in the question, just `3` items) Tim's answer is preferrable; however when list is long, Dictionary will be faster. – Dmitry Bychenko May 03 '18 at 09:57
  • Not over kill, or useless. If order change this will be easier to handle on a list large enought. Even when writing the Dict/List this will be easier as you can seprate the logical order (key order) and the organizational order (Value order) – xdtTransform May 03 '18 at 09:58
  • okay if you want to prevent going through the list over and over for larger lists. but then i would suggest you add a code that shows how to turn the list with values into a dictionary for faster lookup – adjan May 03 '18 at 10:00