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?

10
  • 1
    You can sort in place using a Comparison<T> delegate: stackoverflow.com/a/3309292/860585 Commented Jun 25, 2018 at 12:28
  • 1
    Or an IComparer<T>. But that's not going to work while your parameter is IEnumerable<JObject> - can you change it to a List<JObject>? Commented Jun 25, 2018 at 12:28
  • 1
    use the yield syntax public IEnumerable<JObject> ... 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 Commented Jun 25, 2018 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<JObject>. Commented Jun 25, 2018 at 12:32
  • 2
    Where are those lists you are talking of? Commented Jun 25, 2018 at 12:35

2 Answers 2

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"])));
}
Sign up to request clarification or add additional context in comments.

Comments

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:

3 Comments

Is this not just returning a list though? I need it to be void. It must sort in place
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.
If you again, want to feed a List<> implementation, you probably got a duplicate here of stackoverflow.com/questions/3309188/… as CodeNotFound said

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.