using System.Collections.Generic;
public static class DynamicSort
public static IEnumerable<Dictionary<string, string>> SortByColumns(IEnumerable<Dictionary<string, string>> data, IEnumerable<(string columnName, bool descending)> sortingCriteria)
var comparer = StringComparer.OrdinalIgnoreCase;
var orderedData = OrderByCriterion(data, sortingCriteria.First(), comparer);
foreach (var criterion in sortingCriteria.Skip(1))
orderedData = ThenByCriterion(orderedData, criterion, comparer);
private static IOrderedEnumerable<Dictionary<string, string>> OrderByCriterion(IEnumerable<Dictionary<string, string>> data, (string columnName, bool descending) criterion, StringComparer comparer)
return criterion.descending
? data.OrderByDescending(d => d.ContainsKey(criterion.columnName) ? d[criterion.columnName] : null, comparer)
: data.OrderBy(d => d.ContainsKey(criterion.columnName) ? d[criterion.columnName] : null, comparer);
private static IOrderedEnumerable<Dictionary<string, string>> ThenByCriterion(IOrderedEnumerable<Dictionary<string, string>> data, (string columnName, bool descending) criterion, StringComparer comparer)
return criterion.descending
? data.ThenByDescending(d => d.ContainsKey(criterion.columnName) ? d[criterion.columnName] : null, comparer)
: data.ThenBy(d => d.ContainsKey(criterion.columnName) ? d[criterion.columnName] : null, comparer);
static void Main(string[] args)
var data = new List<Dictionary<string, string>>
new Dictionary<string, string> { { "tagID", "247" }, { "birthTs", "27-03-19" }, { "lactationNumber", "1" }, { "pregnancyCheckTs", "17-06-21" }, { "dryOffTs", "26-07-21" } },
new Dictionary<string, string> { { "tagID", "248" }, { "birthTs", "25-06-14" }, { "lactationNumber", "6" }, { "pregnancyCheckTs", "15-10-21" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "249" }, { "birthTs", "15-06-191" }, { "lactationNumber", "3" }, { "pregnancyCheckTs", "20-08-21" }, { "dryOffTs", "20-09-21" } },
new Dictionary<string, string> { { "tagID", "250" }, { "birthTs", "28-07-191" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "3" }, { "pregnancyCheckTs", "9-03-19" }, { "dryOffTs", "19-04-19" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "3" }, { "pregnancyCheckTs", "9-03-21" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "3" }, { "pregnancyCheckTs", "" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "9-03-21" }, { "dryOffTs", "19-04-21" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "1" }, { "pregnancyCheckTs", "9-03-19" }, { "dryOffTs", "19-04-19" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "1" }, { "pregnancyCheckTs", "9-03-19" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "251" }, { "birthTs", "20-01-18" }, { "lactationNumber", "1" }, { "pregnancyCheckTs", "" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "252" }, { "birthTs", "14-01-18" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "9-03-21" }, { "dryOffTs", "19-04-21" } },
new Dictionary<string, string> { { "tagID", "253" }, { "birthTs", "20-12-181" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "9-07-21" }, { "dryOffTs", "9-08-21" } },
new Dictionary<string, string> { { "tagID", "254" }, { "birthTs", "10-08-173" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "" }, { "dryOffTs", "" } },
new Dictionary<string, string> { { "tagID", "255" }, { "birthTs", "3-08-172" }, { "lactationNumber", "2" }, { "pregnancyCheckTs", "" }, { "dryOffTs", "" } }
var sortingCriteria = new List<(string columnName, bool descending)>
("lactationNumber", false),
("pregnancyCheckTs", true),
var sortedData = DynamicSort.SortByColumns(data, sortingCriteria);
foreach (var row in sortedData)
if(row["tagID"] == "251")
Console.WriteLine(string.Join(", ", row.Select(kv => $"{kv.Key}: {kv.Value}")));