Как настроить сортировку списка строк с учетом желаемой иерархии сортировки? - PullRequest
3 голосов
/ 15 апреля 2020

Я бы хотел отсортировать List<string> определенным образом. Ниже приведен модульный тест, показывающий ввод , специфика c way (который я называю «иерархией» - не стесняйтесь исправлять мою терминологию, чтобы я мог учиться), и желаемый результат . Код должен быть понятен.

[Test]
public void CustomSortByHierarchy()
{
    List<string> input = new List<string>{"TJ", "DJ", "HR", "HR", "TJ"};

    List<string> hierarchy = new List<string>{"HR", "TJ", "DJ" };

    List<string> sorted = input.Sort(hierarchy); // <-- does not compile. How do I sort by the hierarchy?

    // ...and if the sort worked as desired, these assert statements would return true:
    Assert.AreEqual("HR", sorted[0]);
    Assert.AreEqual("HR", sorted[1]);
    Assert.AreEqual("TJ", sorted[2]);
    Assert.AreEqual("TJ", sorted[3]);
    Assert.AreEqual("DJ", sorted[4]);
}

Ответы [ 2 ]

4 голосов
/ 15 апреля 2020

Еще один способ сделать это:

var hierarchy = new Dictionary<string, int>{
    { "HR",  1},
    { "TJ",  2},
    { "DJ",  3} };

var sorted = strings.OrderBy(s => hierarchy[s]).ToList();
2 голосов
/ 16 апреля 2020

Существует так много способов сделать это.

Нехорошо создавать словарь stati c, особенно если у вас есть список значений stati c, уже в том порядке, в котором вы хотите (т.е. List<string> hierarchy = new List<string>{"HR", "TJ", "DJ" };). Проблема со словарем stati c состоит в том, что он stati c - чтобы изменить его, вы должны перекомпилировать свою программу - а также она подвержена ошибкам - вы можете набрать номер неправильно. Лучше всего динамически создавать словарь. Таким образом, вы можете настроить hierarchy во время выполнения и использовать его для заказа input.

Вот базовый c способ создания словаря:

Dictionary<string, int> indices =
    hierarchy
        .Select((value, index) => new { value, index })
        .ToDictionary(x => x.value, x => x.index);

Тогда это простая сортировка:

List<string> sorted = input.OrderBy(x => indices[x]).ToList();

Однако, если у вас отсутствует пропущенное значение в hierarchy, это приведет к исключению KeyNotFoundException.

Попробуйте с этим input:

List<string> input = new List<string> { "TJ", "DJ", "HR", "HR", "TJ", "XX" };

Вам необходимо решить, удаляете ли вы отсутствующие элементы из списка или объединяете их в конце списка.

Чтобы удалить, вы сделаете следующее:

List<string> sorted =
    input
        .Where(x => indices.ContainsKey(x))
        .OrderBy(x => indices[x])
        .ToList();

Или для сортировки до конца вы сделаете это:

List<string> sorted =
    input
        .OrderBy(x => indices.ContainsKey(x) ? indices[x] : int.MaxValue)
        .ThenBy(x => x) // groups missing items together and is optional
        .ToList();

Если вы просто хотите удалить из input элементы, которых нет в hierarchy, тогда Есть несколько других вариантов, которые могут быть привлекательными.

Попробуйте это:

List<string> sorted =
(
    from x in input
    join y in hierarchy.Select((value, index) => new { value, index })
        on x equals y.value
    orderby y.index
    select x
).ToList();

Или это:

ILookup<string, string> lookup = input.ToLookup(x => x);
List<string> sorted = hierarchy.SelectMany(x => lookup[x]).ToList();

Лично мне нравится этот последний. Это два лайнера, и он вообще не зависит от индексов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...