Skip to main content
Some finetuning
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
  1. Splitting the data into different categories ("Cat", "Dog", "Default"). A function which does that may be called like this:

     IEnumerable<T>[] categories 
         =  Categorize(items, new[]("Cat*", "Dog*", "*"));
    

    How you define and implement the prefix filter syntax is up to you and your specific needs, here I suggest to use a "*" as a placeholder for an arbitrary string. You can also use regular expressions here, if you need that.

    Note usage of thisan array is just a simplified example, could be also a dictionary indexed by "Cat*", "Dog*", "*", or some other list of key-value pairs. Note also the order of the category filters is important, the order in which these filter steps have to be applied might be a different order than the one required in step 3.

  2. Sorting the data in each category individually with an individual rule

        categories[0] = categories[0].OrderBy(d=>d.Label);
        categories[1] = categories[1].OrderByDescending(d=>d.Label);
        categories[2] = categories[2].OrderBy(d=>d.Label);
    

    (you could also provide indidividual comparers here, or loop over all categories any apply different sorters, dependent from some other criteria).

  3. Sorting the categories themselves (here "Default", "Cat", "Dog") and merge the data accordingly.

        return categories[2].Concat(categories[0]).Concat(categories[1])
    

    (inI hardcoded this order because the example with 3 categories is very simple. In cases the category order follows a more complicated rule by itselfrules, this may require some more logic to sort, for example, by the category name, or some assigned priority) .

  1. Splitting the data into different categories ("Cat", "Dog", "Default"). A function which does that may be called like this:

     IEnumerable<T>[] categories 
         =  Categorize(items, new[]("Cat*", "Dog*", "*"));
    

    Note usage of this array is just a simplified example, could be also a dictionary indexed by "Cat*", "Dog*", "*", or some other list of key-value pairs. Note also the order of the category filters is important, the order in which these filter steps have to be applied might be a different order than the one required in step 3.

  2. Sorting the data in each category individually with an individual rule

        categories[0] = categories[0].OrderBy(d=>d.Label);
        categories[1] = categories[1].OrderByDescending(d=>d.Label);
        categories[2] = categories[2].OrderBy(d=>d.Label);
    

    (you could also provide indidividual comparers here, or loop over all categories any apply different sorters, dependent from some other criteria).

  3. Sorting the categories themselves (here "Default", "Cat", "Dog") and merge the data accordingly.

        return categories[2].Concat(categories[0]).Concat(categories[1])
    

    (in cases the category order follows a more complicated rule by itself, this may require some more logic to sort, for example, by the category name)

  1. Splitting the data into different categories ("Cat", "Dog", "Default"). A function which does that may be called like this:

     IEnumerable<T>[] categories 
         =  Categorize(items, new[]("Cat*", "Dog*", "*"));
    

    How you define and implement the prefix filter syntax is up to you and your specific needs, here I suggest to use a "*" as a placeholder for an arbitrary string. You can also use regular expressions here, if you need that.

    Note usage of an array is just a simplified example, could be also a dictionary indexed by "Cat*", "Dog*", "*", or some other list of key-value pairs. Note also the order of the category filters is important, the order in which these filter steps have to be applied might be a different order than the one required in step 3.

  2. Sorting the data in each category individually with an individual rule

        categories[0] = categories[0].OrderBy(d=>d.Label);
        categories[1] = categories[1].OrderByDescending(d=>d.Label);
        categories[2] = categories[2].OrderBy(d=>d.Label);
    

    (you could also provide indidividual comparers here, or loop over all categories any apply different sorters, dependent from some other criteria).

  3. Sorting the categories themselves (here "Default", "Cat", "Dog") and merge the data accordingly.

        return categories[2].Concat(categories[0]).Concat(categories[1])
    

    (I hardcoded this order because the example with 3 categories is very simple. In cases the category order follows more complicated rules, this may require some more logic to sort, for example, by the category name, or some assigned priority) .

added 631 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
  • the elements to be sorted

  • an ordered list of pairs of the form

    (string prefixFilter , Func<IEnumerable<T>, IEnumerable<T>> sorter)`
    

    (could be also Func<IEnumerable<string>, IEnumerable<string>> categoryFilter instead of string prefixFilter, if you need it even more generic)

  • an ordering function for the categories themselves (for step 3)

  • the elements to be sorted

So in total:

IEnumerable<T> CategorizedSort(
    IEnumerable<T> items,
    IEnumerable<(string prefixFilter , Func<IEnumerable<T>, IEnumerable<T>> sorter)>,
    Func<IEnumerable<string>, IEnumerable<string>> categorySorter)
     {
         //...
     }

This is called like

orderedItems = CategorizedSort(
       items,
       new[]{("Cat*", cats => cats.OrderBy(d=>d.Label)),
             ("Dog*", dogs => dogs.OrderByDescending(d=>d.Label)),
             ("*", x => x.OrderBy(d.Label))
            },
        MyOrderFunctionForCategories);
  • an ordered list of pairs of the form

    (string prefixFilter , Func<IEnumerable<T>, IEnumerable<T>> sorter)`
    

    (could be also Func<IEnumerable<string>, IEnumerable<string>> categoryFilter instead of string prefixFilter, if you need it even more generic)

  • an ordering function for the categories themselves (for step 3)

  • the elements to be sorted

  • the elements to be sorted

  • an ordered list of pairs of the form

    (string prefixFilter , Func<IEnumerable<T>, IEnumerable<T>> sorter)`
    

    (could be also Func<IEnumerable<string>, IEnumerable<string>> categoryFilter instead of string prefixFilter, if you need it even more generic)

  • an ordering function for the categories themselves (for step 3)

So in total:

IEnumerable<T> CategorizedSort(
    IEnumerable<T> items,
    IEnumerable<(string prefixFilter , Func<IEnumerable<T>, IEnumerable<T>> sorter)>,
    Func<IEnumerable<string>, IEnumerable<string>> categorySorter)
     {
         //...
     }

This is called like

orderedItems = CategorizedSort(
       items,
       new[]{("Cat*", cats => cats.OrderBy(d=>d.Label)),
             ("Dog*", dogs => dogs.OrderByDescending(d=>d.Label)),
             ("*", x => x.OrderBy(d.Label))
            },
        MyOrderFunctionForCategories);
added 22 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625

Sure, it can. A generic function CategorizedSort<T> which does the above requires the following input paramaters:

as input. For nested hierarchies, the individual sorter functors can call this CategorizedSort recursively.

Sure, it can. A generic function CategorizedSort<T> which does the above requires

as input. For nested hierarchies, the individual sorter functors can call this CategorizedSort recursively.

Sure, it can. A generic function CategorizedSort<T> which does the above requires the following input paramaters:

For nested hierarchies, the individual sorter functors can call this CategorizedSort recursively.

added 9 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
Loading
added 254 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
Loading
added 172 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
Loading
added 172 characters in body
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
Loading
Source Link
Doc Brown
  • 220.6k
  • 35
  • 410
  • 625
Loading