c # Курортный список - PullRequest
       2

c # Курортный список

0 голосов
/ 28 октября 2018

Это довольно сложный вид.Обычно я беру список из Ответов и упорядочиваю их по приоритету Вопрос .Приоритет - это целое число, начинающееся с нуля (0 - высший приоритет).Затем я хочу отсортировать каждый ответ по приоритету.Например, вот так:

var answers = new List<AnswerRequestModel>
{
    new AnswerRequestModel
    {
        Id = 1,
        Priority = 0,
        Text = "Very high"
    },
    new AnswerRequestModel
    {
        Id = 2,
        Priority = 1,
        Text = "High"
    },
    new AnswerRequestModel
    {
        Id = 3,
        Priority = 2,
        Text = "Medium"
    },
    new AnswerRequestModel
    {
        Id = 4,
        Priority = 3,
        Text = "Low"
    }
};

Предполагается, что есть только один вопрос.Если было два вопроса:

var answers = new List<AnswerRequestModel>
{
    new AnswerRequestModel
    {
        Id = 1,
        Priority = 0,
        Question = new QuestionRequestModel { Type = QuestionType.Two },
        Text = "Very high",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Very high", Operator = "=", Field = "quality"} }
    },
    new AnswerRequestModel
    {
        Id = 2,
        Priority = 1,
        Question = new QuestionRequestModel { Type = QuestionType.Two },
        Text = "High",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "High", Operator = "=", Field = "quality"} }
    },
    new AnswerRequestModel
    {
        Id = 3,
        Priority = 2,
        Question = new QuestionRequestModel { Type = QuestionType.Two },
        Text = "Medium",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Medium", Operator = "=", Field = "quality"} }
    },
    new AnswerRequestModel
    {
        Id = 4,
        Priority = 3,
        Question = new QuestionRequestModel { Type = QuestionType.Two },
        Text = "Low",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Low", Operator = "=", Field = "quality"} }
    },
    new AnswerRequestModel
    {
        Id = 5,
        Priority = 0,
        Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1},
        Text = "Blacks",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Blacks", Operator = "=", Field = "colour"} }
    },
    new AnswerRequestModel
    {
        Id = 6,
        Priority = 1,
        Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
        Text = "Silvers",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Silvers", Operator = "=", Field = "colour" } }
    },
    new AnswerRequestModel
    {
        Id = 7,
        Priority = 2,
        Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
        Text = "Reds",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Blues", Operator = "=", Field = "colour" } }
    },
    new AnswerRequestModel
    {
        Id = 8,
        Priority = 3,
        Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
        Text = "Yellows",
        Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Yellows", Operator = "=", Field = "colour" } }
    }
};

В обоих этих примерах порядок правильный.Но сейчас приходит осложнение.Если я выберу ответ.Мне нужно прибегнуть к помощи, также если ответы и вопросы приходят в неправильном порядке, я хочу, чтобы они были отсортированы правильно.Этот метод также должен работать при выборе нескольких ответов.

Мой метод в настоящее время выглядит следующим образом:

public IList<AnswerRequestModel> SortAnswersByPriority(IList<AnswerRequestModel> answers)
{
    if (!answers.Any()) return answers;

    var chosenAnswers = answers.Where(m => m.Active).ToList();
    var sortedAnswers = answers.OrderBy(m => m.Question.Priority).ThenBy(m => m.Priority);

    if (!chosenAnswers.Any())
        return sortedAnswers.ToList();

    var questionIds = answers.GroupBy(m => m.Question.Id).Select(m => m.Key).ToList();
    foreach(var questionId in questionIds)
    {
        var questionAnswers = answers.Where(m => m.Question.Id == questionId).ToList();
        if (!questionAnswers.Any()) continue;

        var highestPriority = questionAnswers.OrderBy(m => m.Priority).First().Priority;
        var chosenQuestionAnswers = answers.Where(m => m.Active).ToList();
        var count = chosenQuestionAnswers.Count;

        var ordered = questionAnswers.OrderBy(a => 1);
        switch (count)
        {
            case 1:
                var choseHighest = chosenQuestionAnswers.SingleOrDefault(m => m.Priority.Equals(highestPriority)) != null;
                ordered = choseHighest ? ordered.OrderBy(m => m.Priority) : ordered.OrderByDescending(m => m.Priority);
                break;
            default:
                ordered = ordered.ThenByDescending(m => m.Active).ThenByDescending(m => m.Priority);
                break;
        }

        var questionAnswerIds = ordered.Select(m => m.Id).ToList();
        sortedAnswers = sortedAnswers.ThenBy(m => questionAnswerIds.IndexOf(m.Id));
    }

    return sortedAnswers.ToList();
}

Если поставить точку останова на sortedAnswers = sortedAnswers.ThenBy(m => questionAnswerIds.IndexOf(m.Id));, я вижу, что мой сортировка работаетправильно, потому что идентификаторы ответов отсортированы.Но когда он выполняет строку с точкой останова, ничего не меняется.

Может кто-нибудь помочь мне разобраться?

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Я решил это, но я думаю, что это была проблема с моей логикой, а не с чем-либо еще.Я изменил свой метод на следующий:

public IList<AnswerRequestModel> SortAnswersByPriority(IList<AnswerRequestModel> answers)
{
    if (!answers.Any()) return answers;

    var chosenAnswers = answers.Where(m => m.Active).ToList();

    // If we have no chosen answers, then just do a default sort by priority
    if (!chosenAnswers.Any()) return answers.OrderBy(m => m.Question.Priority).ThenBy(m => m.Priority).ToList();

    var sortedAnswers = answers.OrderBy(a => 1);
    var questionIds = answers.GroupBy(m => m.Question.Id).Select(m => m.Key).ToList();
    foreach(var questionId in questionIds)
    {
        var questionAnswers = answers.Where(m => m.Question.Id == questionId).ToList();
        if (!questionAnswers.Any()) continue;

        var lowestPriority = questionAnswers.OrderByDescending(m => m.Priority).First().Priority;
        var chosenQuestionAnswers = answers.Where(m => m.Active).ToList();
        var count = chosenQuestionAnswers.Count;
        var ordered = questionAnswers.OrderBy(a => 1);

        // Sort by our chosen answers first, then by answer priority
        if (chosenQuestionAnswers.Any(m => m.Priority.Equals(lowestPriority)))
        {
            switch (count)
            {
                case 1:
                    ordered = ordered.OrderByDescending(m => m.Priority);
                    break;
                default:
                    ordered = ordered.OrderByDescending(m => m.Active).ThenByDescending(m => m.Priority);
                    break;
            }
        } else
        {
            ordered = ordered.OrderByDescending(m => m.Active).ThenBy(m => m.Priority);
        }

        var questionAnswerIds = ordered.Select(m => m.Id).ToList();
        sortedAnswers = sortedAnswers.ThenBy(m => questionAnswerIds.IndexOf(m.Id));
    }

    // Once we have sorted by our answer priority, do a final sort on question priority and return the list
    return sortedAnswers.OrderBy(m => m.Question.Priority).ToList();
}

, и в ответ на @mjwills приведенного мною кода должно хватить для того, чтобы вы работали локально.Если вы создали модель AnswerRequestModel и метод SortAnswersByPriority и передали список, который я использовал в моем примере, вы сможете выполнить его без проблем.

Я мог бы предоставитьмой юнит тест:

[Test]
public void ShouldSortOnMultipleQuestionsWithOneChosenAnswerPerQuestion()
{
    // Assemble
    var services = SortContext.GivenServices();
    var sortProvider = services.WhenCreateSortProvider();
    var answers = new List<AnswerRequestModel>
    {
        new AnswerRequestModel
        {
            Id = 1,
            Priority = 0,
            Question = new QuestionRequestModel { Type = QuestionType.Two },
            Text = "Very high",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Very high", Operator = "=", Field = "quality"} }
        },
        new AnswerRequestModel
        {
            Id = 2,
            Priority = 1,
            Question = new QuestionRequestModel { Type = QuestionType.Two },
            Text = "High",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "High", Operator = "=", Field = "quality"} }
        },
        new AnswerRequestModel
        {
            Id = 3,
            Priority = 2,
            Question = new QuestionRequestModel { Type = QuestionType.Two },
            Text = "Medium",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Medium", Operator = "=", Field = "quality"} }
        },
        new AnswerRequestModel
        {
            Id = 4,
            Priority = 3,
            Question = new QuestionRequestModel { Type = QuestionType.Two },
            Text = "Low",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Low", Operator = "=", Field = "quality"} }
        },
        new AnswerRequestModel
        {
            Id = 5,
            Priority = 0,
            Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1},
            Text = "Blacks",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Blacks", Operator = "=", Field = "colour"} }
        },
        new AnswerRequestModel
        {
            Id = 6,
            Priority = 1,
            Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
            Text = "Silvers",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Silvers", Operator = "=", Field = "colour" } }
        },
        new AnswerRequestModel
        {
            Id = 7,
            Priority = 2,
            Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
            Text = "Reds",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Blues", Operator = "=", Field = "colour" } }
        },
        new AnswerRequestModel
        {
            Id = 8,
            Priority = 3,
            Question = new QuestionRequestModel { Type = QuestionType.Two, Priority = 1 },
            Text = "Yellows",
            Formulas = new List<AnswerFormula> { new AnswerFormula { Expression = "Yellows", Operator = "=", Field = "colour" } }
        }
    };
    answers[1].Active = true;
    answers[6].Active = true;

    // Act
    var sortedAnswers = sortProvider.SortAnswersByPriority(answers);
    var firstAnswer = sortedAnswers[0];
    var secondAnswer = sortedAnswers[1];
    var thirdAnswer = sortedAnswers[2];
    var forthAnswer = sortedAnswers[3];
    var fifthAnswer = sortedAnswers[4];
    var sixthAnswer = sortedAnswers[5];
    var seventhAnswer = sortedAnswers[6];
    var eigthAnswer = sortedAnswers[7];

    // Assert
    firstAnswer.Text.Should().Be("High");
    secondAnswer.Text.Should().Be("Very high");
    thirdAnswer.Text.Should().Be("Medium");
    forthAnswer.Text.Should().Be("Low");
    fifthAnswer.Text.Should().Be("Reds");
    sixthAnswer.Text.Should().Be("Blacks");
    seventhAnswer.Text.Should().Be("Silvers");
    eigthAnswer.Text.Should().Be("Yellows");
}
0 голосов
/ 28 октября 2018

Если ваша точка останова не указана после ToList (), вы не увидите изменений.Методы OrderBy / ThenBy реализованы с использованием отложенного выполнения.Пока вы не начнете перечислять запрос ThenBy (т.е. используя foreach или ToList / ToArray), вы не увидите никаких изменений.

sortedAnswers = sortedAnswers
    .ThenBy(m => questionAnswerIds.IndexOf(m.Id))
    .ToList(); // put your break point after this line
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...