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

Bardziej eleganckie sposoby na rozwiązanie zadań z wyrażeniami LINQ
BU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 422
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 **

Kopiuj
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 **

Kopiuj
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 **

Kopiuj
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 **

Kopiuj
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 **

Kopiuj
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 **

Kopiuj
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())))));
neves
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 1114
2

Zadanie 1

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

Zadanie 2
nie widzę znacznie lepszej wersji

Zadanie 3

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

Zadanie 4

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

Zadanie 5
Też wygląda dobrze.

Zadanie 6

Kopiuj
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)));
BU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 422
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...

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.