I need to split the list into several lists, which are grouped according to the first character of the string property. Here is an example.
class Program { static void Main(string[] args) { var makes = new List<VehicleMake> { new VehicleMake {Name = "Acura"}, new VehicleMake {Name = "AMG"}, new VehicleMake {Name = "Audi"}, new VehicleMake {Name = "BMW"}, new VehicleMake {Name = "Chevrolet"}, new VehicleMake {Name = "Datsun"}, new VehicleMake {Name = "Eagle"}, new VehicleMake {Name = "Fiat"}, new VehicleMake {Name = "Honda"}, new VehicleMake {Name = "Infiniti"}, new VehicleMake {Name = "Jaguar"} }; var balancedLists = makes.Balance(new List<BalancedListGroup> { new BalancedListGroup { RangeStart = 'A', RangeEnd = 'C'}, new BalancedListGroup { RangeStart = 'D', RangeEnd = 'F'}, new BalancedListGroup { RangeStart = 'G', RangeEnd = 'J'}, }); foreach (var balancedList in balancedLists) { foreach (var vehicleMake in balancedList) { Console.WriteLine(vehicleMake.Name); } Console.WriteLine("---"); } Console.ReadLine(); } } public class VehicleMake { public string Name { get; set; } } public static class VehicleMakeListBalancer { public static List<List<VehicleMake>> Balance(this List<VehicleMake> list, List<BalancedListGroup> groups) { var letters = new List<string> { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "y", "z" }; var balancedLists = new List<List<VehicleMake>>(); foreach (var group in groups) { var groupList = new List<VehicleMake>(); for (var i = letters.IndexOf(group.RangeStart.ToString().ToLower()); i <= letters.IndexOf(group.RangeEnd.ToString().ToLower()); i++) { groupList.AddRange(list.Where(l => l.Name.ToLower().StartsWith(letters[i].ToString())).ToList()); } balancedLists.Add(groupList); } return balancedLists; } } public class BalancedListGroup { public char RangeStart { get; set; } public char RangeEnd { get; set; } }
What outputs:
Acura AMG Audi BMW Chevrolet --- Datsun Eagle Fiat --- Honda Infiniti Jaguar ---
This algorithm works, but feels very awkward. Is there a more elegant way to do this?