C# лямбда как заказать Список по детскому описанию - PullRequest
0 голосов
/ 12 марта 2020

У меня есть следующий класс:

  public class Result
    {
        public string Description { get; set; }
        public DateTime StartTime { get; set; }
        public TimeSpan Elapsed { get; set; }
        public List<Result> Actions { get; set; }

    }

Затем я создаю список задач следующим образом:

 List<Task<Result>> tasksToRun = new List<Task<Result>>();

Затем несколько задач будут выполняться одновременно, и после того, как все сделано, я хочу напечатать результаты в текстовом поле.

Прямо сейчас я задаю oop задач и получаю результат и начинаю создавать мой построитель строк, и работает

 foreach (var task in tasksToRun)
            {
                var result = task.Result;

                sb.Append(result.Description);
                sb.Append(Environment.NewLine);
                sb.Append(result.StartTime);
                sb.Append(Environment.NewLine);

                foreach(var action in result.Actions)
                {
                    elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                        action.Elapsed.Hours, action.Elapsed.Minutes, action.Elapsed.Seconds,
                        action.Elapsed.Milliseconds / 10);
                    sb.Append("    -----------------  ");
                    sb.Append(Environment.NewLine);
                    sb.Append("    " + action.Description);
                    sb.Append(Environment.NewLine);
                    sb.Append("    " + elapsedTime);
                    sb.Append(Environment.NewLine);
                    sb.Append("    -----------------  ");
                }

                sb.Append(Environment.NewLine);

                elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                        result.Elapsed.Hours, result.Elapsed.Minutes, result.Elapsed.Seconds,
                        result.Elapsed.Milliseconds / 10);

                sb.Append(elapsedTime);
                sb.Append(Environment.NewLine);
                sb.Append(Environment.NewLine);
                sb.Append(Environment.NewLine);

                txtResult.Text = sb.ToString();
            }

Мой результат вывода :

Main
12/03/2020 11:09:31 a. m.
    -----------------  
    ValidateUser
    00:00:00.95
    -----------------      -----------------  
    GetInvoiceList
    00:00:12.73
    -----------------      -----------------  
    SearchFolio
    00:00:04.17
    -----------------      -----------------  
    SearchPatients
    00:00:06.12
    -----------------      -----------------  
    SearchOrganization
    00:00:08.60
    -----------------  
00:00:32.63


Main
12/03/2020 11:09:31 a. m.
    -----------------  
    ValidateUser
    00:00:00.49
    -----------------      -----------------  
    SearchFolio
    00:00:03.69
    -----------------      -----------------  
    GetInvoiceList
    00:00:10.15
    -----------------      -----------------  
    SearchOrganization
    00:00:00.55
    -----------------      -----------------  
    SearchPatients
    00:00:06.91
    -----------------  
00:00:21.85


Main
12/03/2020 11:09:31 a. m.
    -----------------  
    ValidateUser
    00:00:00.84
    -----------------      -----------------  
    SearchFolio
    00:00:07.29
    -----------------      -----------------  
    SearchOrganization
    00:00:05.99
    -----------------      -----------------  
    SearchPatients
    00:00:07.70
    -----------------      -----------------  
    GetInvoiceList
    00:00:10.45
    -----------------  
00:00:32.32

Я хочу напечатать в качестве отдельной опции список только дочерних действий и групп по одному описанию, поэтому я должен получить что-то вроде этого:

 -----------------  
    ValidateUser
    00:00:00.95
    -----------------      -----------------  
    ValidateUser
    00:00:00.49
    -----------------      -----------------  
    ValidateUser
    00:00:00.84
    -----------------      -----------------  


    GetInvoiceList
    00:00:12.73
    -----------------      -----------------  
    GetInvoiceList
    00:00:10.15
    -----------------      -----------------  
    GetInvoiceList
    00:00:10.45
    -----------------      -----------------  


    SearchFolio
    00:00:04.17
    -----------------      -----------------  
    SearchFolio
    00:00:03.69
    -----------------      -----------------  
    SearchFolio
    00:00:07.29
    -----------------      -----------------  


    SearchPatients
    00:00:06.12
    -----------------      -----------------  
    SearchPatients
    00:00:06.91
    -----------------      -----------------  
    SearchPatients
    00:00:07.70
    -----------------      -----------------  


    SearchOrganization
    00:00:08.60
    -----------------  
    SearchOrganization
    00:00:00.55
    -----------------      -----------------
    SearchOrganization
    00:00:05.99
    -----------------      -----------------    

Пытался так:

tasksToRun.OrderBy(t=> t.Result.Actions.Descritpion)

Но поскольку Actions является списком, я не могу получить свойство Description напрямую. Должно быть простое решение.

Любая подсказка?

Ответы [ 4 ]

0 голосов
/ 13 марта 2020

Если у вас есть List<Result>, называемый results, то вот ключевая часть, которую вам нужно сделать:

    from result in results
    from action in result.Actions
    group action by action.Description into actions

Вот мой полный код для решения вашей проблемы:

var results = new List<Result>()
{
    new Result()
    {
        Description = "Main",
        StartTime = new DateTime(2020, 3, 12, 11, 9, 31),
        Actions = new List<Result>()
        {
            new Result() { Description = "ValidateUser", Elapsed = TimeSpan.FromSeconds(0.95), },
            new Result() { Description = "GetInvoiceList", Elapsed = TimeSpan.FromSeconds(12.73), },
            new Result() { Description = "SearchFolio", Elapsed = TimeSpan.FromSeconds(4.17), },
            new Result() { Description = "SearchPatients", Elapsed = TimeSpan.FromSeconds(6.12), },
            new Result() { Description = "SearchOrganization", Elapsed = TimeSpan.FromSeconds(8.6), },
        }
    },
    new Result()
    {
        Description = "Main",
        StartTime = new DateTime(2020, 3, 12, 11, 9, 31),
        Actions = new List<Result>()
        {
            new Result() { Description = "ValidateUser", Elapsed = TimeSpan.FromSeconds(0.49), },
            new Result() { Description = "SearchFolio", Elapsed = TimeSpan.FromSeconds(3.69), },
            new Result() { Description = "GetInvoiceList", Elapsed = TimeSpan.FromSeconds(10.15), },
            new Result() { Description = "SearchOrganization", Elapsed = TimeSpan.FromSeconds(0.55), },
            new Result() { Description = "SearchPatients", Elapsed = TimeSpan.FromSeconds(6.91), },
        }
    },
    new Result()
    {
        Description = "Main",
        StartTime = new DateTime(2020, 3, 12, 11, 9, 31),
        Actions = new List<Result>()
        {
            new Result() { Description = "ValidateUser", Elapsed = TimeSpan.FromSeconds(0.84), },
            new Result() { Description = "SearchFolio", Elapsed = TimeSpan.FromSeconds(7.29), },
            new Result() { Description = "SearchOrganization", Elapsed = TimeSpan.FromSeconds(5.99), },
            new Result() { Description = "SearchPatients", Elapsed = TimeSpan.FromSeconds(7.70), },
            new Result() { Description = "GetInvoiceList", Elapsed = TimeSpan.FromSeconds(10.45), },
        }
    },
};

string ElaspedTime(TimeSpan elapsed) => $"{elapsed.Hours:00}:{elapsed.Minutes:00}:{elapsed.Seconds:00}.{(elapsed.Milliseconds / 10):00}";

var output1 =
    String.Join(
        Environment.NewLine + Environment.NewLine, 
        from result in results
        let header = new []
        {
            result.Description,
            result.StartTime.ToString(),
        }
        let details =
            result
                .Actions
                    .SelectMany(action => new[]
                    {
                        "-----------------",
                        action.Description,
                        ElaspedTime(action.Elapsed)
                    })
                    .Concat(new[] { "-----------------" })
                    .Select(x => $"    {x}")
        let tail = new[]
        {
            ElaspedTime(result.Actions.Select(x => x.Elapsed).Aggregate((x, y) => x.Add(y))),
        }
        select String.Join(Environment.NewLine, header.Concat(details).Concat(tail)));

var output2 =
    String.Join(
        Environment.NewLine + Environment.NewLine,
        from result in results
        from action in result.Actions
        group action by action.Description into actions
        let details =
            actions
                    .SelectMany(action => new[]
                    {
                        "-----------------",
                        action.Description,
                        ElaspedTime(action.Elapsed)
                    })
                    .Concat(new[] { "-----------------" })
                    .Select(x => $"    {x}")
        select String.Join(Environment.NewLine, details));

Для output1 Я получаю:

Main
2020/03/12 11:09:31
    -----------------
    ValidateUser
    00:00:00.95
    -----------------
    GetInvoiceList
    00:00:12.73
    -----------------
    SearchFolio
    00:00:04.17
    -----------------
    SearchPatients
    00:00:06.12
    -----------------
    SearchOrganization
    00:00:08.60
    -----------------
00:00:32.57

Main
2020/03/12 11:09:31
    -----------------
    ValidateUser
    00:00:00.49
    -----------------
    SearchFolio
    00:00:03.69
    -----------------
    GetInvoiceList
    00:00:10.15
    -----------------
    SearchOrganization
    00:00:00.55
    -----------------
    SearchPatients
    00:00:06.91
    -----------------
00:00:21.79

Main
2020/03/12 11:09:31
    -----------------
    ValidateUser
    00:00:00.84
    -----------------
    SearchFolio
    00:00:07.29
    -----------------
    SearchOrganization
    00:00:05.99
    -----------------
    SearchPatients
    00:00:07.70
    -----------------
    GetInvoiceList
    00:00:10.45
    -----------------
00:00:32.27

Для output2 Я получаю:

    -----------------
    ValidateUser
    00:00:00.95
    -----------------
    ValidateUser
    00:00:00.49
    -----------------
    ValidateUser
    00:00:00.84
    -----------------

    -----------------
    GetInvoiceList
    00:00:12.73
    -----------------
    GetInvoiceList
    00:00:10.15
    -----------------
    GetInvoiceList
    00:00:10.45
    -----------------

    -----------------
    SearchFolio
    00:00:04.17
    -----------------
    SearchFolio
    00:00:03.69
    -----------------
    SearchFolio
    00:00:07.29
    -----------------

    -----------------
    SearchPatients
    00:00:06.12
    -----------------
    SearchPatients
    00:00:06.91
    -----------------
    SearchPatients
    00:00:07.70
    -----------------

    -----------------
    SearchOrganization
    00:00:08.60
    -----------------
    SearchOrganization
    00:00:00.55
    -----------------
    SearchOrganization
    00:00:05.99
    -----------------
0 голосов
/ 12 марта 2020

Вот рабочий пример. Также выводится в окне отладки enter image description here

public class Result
{
    public string Description { get; set; }
    public DateTime StartTime { get; set; }
    public TimeSpan Elapsed { get; set; }
    public List<Result> Actions { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // Initialize some test data
        Result r1 = new Result()
        {
            Description = "Res1",
            StartTime = new DateTime(2020, 3, 1),
            Elapsed = new TimeSpan(12),
            Actions = new List<Result>() { }
        };
        Result r2 = new Result()
        {
            Description = "Res2",
            StartTime = new DateTime(2021, 3, 1),
            Elapsed = new TimeSpan(22),
            Actions = new List<Result>() { }
        };
        Result r3 = new Result()
        {
            Description = "Res3",
            StartTime = new DateTime(2022, 3, 1),
            Elapsed = new TimeSpan(3),
            Actions = new List<Result>() { }
        };

        List<Result> a1 = new List<Result>() { r1, r2, r3 };
        List<Result> a2 = new List<Result>() { r1, r2, r3 };
        List<Task<Result>> tasksToRun = new List<Task<Result>>();
        StringBuilder sb = new StringBuilder();

        Task<Result> t1 = Task<Result>.Factory.StartNew(() => new Result()
        {
            Description = "x1",
            StartTime = new DateTime(2020,2,2),
            Elapsed = new TimeSpan(2),
            Actions = a1
        });

        Task<Result> t2 = Task<Result>.Factory.StartNew(() => new Result()
        {
            Description = "x2",
            StartTime = DateTime.Now,
            Elapsed = new TimeSpan(33),
            Actions = a2
        });
        tasksToRun.Add(t1);
        tasksToRun.Add(t2);
        List<Result> holder = new List<Result>();

        // Run each tasks
        foreach (var task in tasksToRun)
        {
            var result = task.Result;
            foreach (var action in result.Actions)
            {
                holder.Add(action);
            }
        }

        // Re-arrange in the desired format
        string currentDesc = "";
        foreach (var action in holder.OrderBy(x => x.Description))
        {
            if(currentDesc != "" &&
                currentDesc != action.Description
              )
            {
                sb.Append(Environment.NewLine);
                sb.Append("********************");
            }

            var elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                action.Elapsed.Hours, action.Elapsed.Minutes, action.Elapsed.Seconds,
                action.Elapsed.Milliseconds / 10);
            sb.Append("    -----------------  ");
            sb.Append(Environment.NewLine);
            sb.Append("    " + action.Description);
            sb.Append(Environment.NewLine);
            sb.Append("    " + elapsedTime);
            sb.Append(Environment.NewLine);
            sb.Append("    -----------------  ");
            currentDesc = action.Description;
        }

        var ss = sb.ToString();
    }
}
0 голосов
/ 13 марта 2020

Используя Linq, вы можете собрать все Actions из каждого Result с помощью SelectMany, а затем сгруппировать их по Description для вывода:

foreach (var actionTaskGroup in tasksToRun.SelectMany(t => t.Result.Actions).GroupBy(a => a.Description)) {
    foreach (var action in actionTaskGroup) {
        var elapsedTime = action.Elapsed.ToString(@"hh\:mm\:ss\.ff");
        sb.Append("    -----------------  \n");
        sb.Append($"    {action.Description}\n");
        sb.Append($"    {elapsedTime}\n");
        sb.Append("    -----------------  ");
    }

    sb.Append("    -----------------  \n");
    sb.Append(Environment.NewLine);
    sb.Append(Environment.NewLine);

    txtResult.Text = sb.ToString();
}
0 голосов
/ 12 марта 2020

Два варианта:

Если вы предполагаете, что каждое действие будет иметь только одно отдельное описание, вы можете попробовать это:

tasksToRun.OrderBy(t=> t.Result.Actions.First().Descritpion)

Если каждое действие имеет много разных описаний, вы можете попробуйте это:

tasksToRun.OrderBy(t=> t.Result.Actions.OrderBy(a => 
        a.Description).First().Descritpion)

Затем вы будете упорядочивать все описания для каждого действия, а затем упорядочивать весь список по первому описанию каждого действия.

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