Bardziej eleganckie sposoby na rozwiązanie zadań z wyrażeniami LINQ

0

Chciałbym poznać sprytniejsze i bardziej zwięzłe (niż moje) rozwiązania zadań ze strony https://markheath.net/post/lunchtime-linq-challenge. Interesują mnie tylko takie rozwiązania, które nie używają pomocniczych zmiennych i zawierają tylko jedną instrukcję LINQ, która w lambdach nie zawiera bloków instrukcji.

Treść zadań:

Each of these problems can be solved using a single C# statement by making use of chained LINQ operators (although you can use more statements if you like). You'll find the String.Split function helpful to get started on each problem. Other functions you might need to use at various points are String.Join, Enumerable.Range, Zip, Aggregate, SelectMany. LINQPad would be a good choice to try out your ideas.

  1. Take the following string Davis, Clyne, Fonte, Hooiveld, Shaw, Davis, Schneiderlin, Cork, Lallana, Rodriguez, Lambert and give each player a shirt number, starting from 1, to create a string of the form: 1. Davis, 2. Clyne, 3. Fonte etc

  2. Take the following string Jason Puncheon, 26/06/1986; Jos Hooiveld, 22/04/1983; Kelvin Davis, 29/09/1976; Luke Shaw, 12/07/1995; Gaston Ramirez, 02/12/1990; Adam Lallana, 10/05/1988 and turn it into an IEnumerable of players in order of age (bonus to show the age in the output)

  3. Take the following string 4:12,2:43,3:51,4:29,3:24,3:14,4:46,3:25,4:52,3:27 which represents the durations of songs in minutes and seconds, and calculate the total duration of the whole album

  4. Create an enumerable sequence of strings in the form x,y representing all the points on a 3x3 grid. e.g. output would be: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2

  5. Take the following string 00:45,01:32,02:18,03:01,03:44,04:31,05:19,06:01,06:47,07:35 which represents the times (in minutes and seconds) at which a swimmer completed each of 10 lengths. Turn this into an IEnumerable of TimeSpan objects containing the time taken to swim each length (e.g. first length was 45 seconds, second was 47 seconds etc)

  6. Take the following string 2,5,7-10,11,17-18 and turn it into an IEnumerable of integers: 2 5 7 8 9 10 11 17 18

** Moje rozwiązania: **

** Zadanie 1 **

var input = "Davis, Clyne, Fonte, Hooiveld, Shaw, Davis, Schneiderlin, Cork, Lallana, Rodriguez, Lambert";

var output = string.Join(", ", input
    .Split(new[] { ", " }, StringSplitOptions.None)
    .Zip(Enumerable.Range(1, int.MaxValue), (x1, x2) => $"{x2.ToString()}. {x1}"));

** Zadanie 2 **

var input = "Jason Puncheon, 26/06/1986; Jos Hooiveld, 22/04/1983; Kelvin Davis, 29/09/1976; Luke Shaw, 12/07/1995; Gaston Ramirez, 02/12/1990; Adam Lallana, 10/05/1988";

var output = input
    .Split(new[] { "; " }, StringSplitOptions.None)
    .Select(x => x.Split(new[] { ", " }, StringSplitOptions.None))
    .Select(x => new
    {
        Name = x[0],
        Age = (DateTime.Now - DateTime.Parse(x[1])).Days / 365
    })
    .OrderBy(x => x.Age);

** Zadanie 3 **

var input = "4:12,2:43,3:51,4:29,3:24,3:14,4:46,3:25,4:52,3:27";

var output = input
    .Split(',')
    .Select(x => x.Split(':'))
    .Aggregate((x1, x2) => new[] {
        (int.Parse(x1[0]) + int.Parse(x2[0])).ToString(),
        (int.Parse(x1[1]) + int.Parse(x2[1])).ToString()
    })
    .Aggregate((x1, x2) => $"{int.Parse(x1) + int.Parse(x2) / 60}:{int.Parse(x2) % 60}");

** Zadanie 4 **

var output = string.Join(" ", Enumerable
    .Range(0, 3)
    .SelectMany(x => Enumerable.Repeat(x, 3).Zip(
        Enumerable.Range(0, 3),
        (x1, x2) => $"{x1},{x2}")));

** Zadanie 5 **

var input1 = "00:45,01:32,02:18,03:01,03:44,04:31,05:19,06:01,06:47,07:35";

var output = input1
    .Split(',')
    .Zip(("00:00," + input1)
        .Split(','),
        (x1, x2) => TimeSpan.Parse("00:" + x1) - TimeSpan.Parse("00:" + x2));

** Zadanie 6 **

var input1 = "2,5,7-10,11,17-18";

var output = string.Join(" ", input1
    .Split(',')
    .Select(x => !x.Contains('-') ?
        x :
        x.Split('-')
            .Aggregate((x1, x2) => string.Join(" ", Enumerable
                .Range(int.Parse(x1), int.Parse(x2) - int.Parse(x1) + 1)
                .Select(y => y.ToString())))));
2

Zadanie 1

var output = string.Join(", ", input.Split(',').Select((x, y) => $"{y+1}. {x.Trim()}"));

Zadanie 2
nie widzę znacznie lepszej wersji

Zadanie 3

var output = input
          .Split(',')
          .Select(x => TimeSpan.Parse("0:"+ x))
          .Aggregate((x1, x2) => x1+x2);

Zadanie 4

var output = String.Join(" ", Enumerable.Range(0, 9).Select(x => $"{x/3},{x%3}"));

Zadanie 5
Też wygląda dobrze.

Zadanie 6

var output = string.Join(" ", input1
         .Split(',')
         .Select(x => x.Split('-').Select(y => int.Parse(y))) 
         .SelectMany(x => Enumerable.Range( x.First(), x.Last() - x.First() + 1)));
0

Dzięki za pomoc. Najbardziej mi brakowało uzyskania indeksu elementu i dziwiłem się, że nie ma takiej możliwości, a jednak metoda select to umożliwia...

1 użytkowników online, w tym zalogowanych: 0, gości: 1