1

I have 2 lists, one is the original list and the other is a sorted list. I want to sort the first list by the second list, but my method will not return anything, so it must sort the list in place.

I did this method:

public void SortByList(IEnumerable<JObject> source, IEnumerable<JObject> products)
{
    var ids = source.Select(m => m["_id"].ToString()).ToList();
    products.OrderBy(m => ids.IndexOf(m["_id"].ToString()));
}

But as you know, OrderBy creates a new list. How can I Sort using the ids?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
r3plica
  • 13,017
  • 23
  • 128
  • 290
  • 1
    You can sort in place using a `Comparison` delegate: https://stackoverflow.com/a/3309292/860585 – Rotem Jun 25 '18 at 12:28
  • 1
    Or an `IComparer`. But that's not going to work while your parameter is `IEnumerable` - can you change it to a `List`? – Jon Skeet Jun 25 '18 at 12:28
  • Yeah, but that just sorts based on a property on the list I am sorting. How can I get it to sort based on the order of the other list? – r3plica Jun 25 '18 at 12:30
  • What´s your problem on a new list? Sorting will consume lots of memory anyway (and probably will internally copy the original list), I guess the overhead of a second copy can be omitted. – MakePeaceGreatAgain Jun 25 '18 at 12:30
  • Possible duplicate of [How to Sort a List by a property in the object](https://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object) – CodeNotFound Jun 25 '18 at 12:31
  • 1
    use the yield syntax `public IEnumerable ...` and inside of the method, you write actual code. But instead of returning a list, you use `yield return` to return a single entry. C# will do all the magic required to make it an `IEnumerable<>` to further enhance, you can then make the method a static extension by making the method static and adding a `this` in front of source – X39 Jun 25 '18 at 12:31
  • 1
    The method @X39 suggests is the only option if you need it to remain an `IEnumerable`. Otherwise in order to sort it you would have to convert it to a concrete type, e.g. `List`. – Rotem Jun 25 '18 at 12:32
  • 2
    Where are those lists you are talking of? – Tim Schmelter Jun 25 '18 at 12:35
  • 1
    if these were *arrays*, there exist dual array sorting methods – Marc Gravell Jun 25 '18 at 12:38
  • @CodeNotFound this is not a duplicate....... can you remove it please – r3plica Jun 25 '18 at 12:40

2 Answers2

1

Use the yield syntax:

//Returns source sorted by products
//Due to usage of the `this` keyword on the `IEnumerable<JObject> source` parameter,
//this method can be called like a member method on any instance imlpementing `IEnumerable<JObject>`.
public static class MyProductExtensionMethods {
    public static IEnumerable<JObject> SortByList(this IEnumerable<JObject> source,
                IEnumerable<JObject> products) {
        foreach(var prod in products) {
            // sorting happens here and assigning the next sorted item
            // to the variable  `sorted_next` (sorting part obviously not provided)
            yield return sorted_next;
        }
    }
}

more on that topic:

X39
  • 789
  • 6
  • 22
  • Is this not just returning a list though? I need it to be void. It must sort in place – r3plica Jun 25 '18 at 12:41
  • sort in place is not working with `IEnumerable<>` at all (see the IEnumerator interface for more on why it is not, short version: it was never supposed to support something like that). If you need it to sort in-place, you need to pass a valid, sortable list or array. This method gives you a separate `IEnumerable<>` based on what you fed it. – X39 Jun 25 '18 at 12:42
  • If you again, want to feed a `List<>` implementation, you probably got a duplicate here of https://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object as CodeNotFound said – X39 Jun 25 '18 at 12:49
1

Well, there are no lists, so i assume that you actually pass lists. If you don't want to create a new list you have to cast it to list or change the parameter type to List<T>. Then you can use List.Sort:

public void SortByList(List<JObject> sourceList, IEnumerable<JObject> products)
{
    List<JObject> productList = products as List<JObject> ?? products.ToList();
    sourceList.Sort((x1, x2) => productList
        .FindIndex(p => p["_id"] == x1["_id"])
        .CompareTo(productList.FindIndex(p => p["_id"] == x2["_id"])));
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939