CodeGolf - как в Linq вызвать объект на котором он был вызван?
Есть следующий код :
var data = JsonSerializer.Deserialize<int[]>(Console.ReadLine()).ToList();
Console.Write(data.Zip(data.Skip(1), (f, s) => f == s).Count(x => x));
Он работает корректно, но можно ли его ещё сильнее сократить? Я вызываю переменную "data" дважды. Сперва на ней вызывается метод Zip, а потом она же выступает в качестве аргумента в этом методе. Можно ли как-то в методе указать, что аргументом нужно брать объект на котором он был вызван? Или может быть тут как-то можно сделать через вызов другого метода? В общем возможно ли решить данную задачу в одну строчку?
Сама задача, которую решает код вот :
У вас есть переменная data которая содержит входные пользовательские данные. data - список из элементов целых числел. Напишите код, который находит количество серий из подряд идущих одинаковых чисел. Результат записать в переменную result. Например, в таком списке [1, 2, 2, 3, 3, 3, 4, 4, 4, 4] - 6 серий
Ответы (3 шт):
По сути вам надо хранить предыдущие значение и количество серии на каждой итерации. Для этого есть метод Aggregate в Linq. Который может это хранить у себя и вернуть как результат эту структуру, а из ней уже можно взять количество серии
var (result, _) = data.Aggregate((0, (int?)null), (acc, nxt) => (nxt == acc.Item2 ? ++acc.Item1 : acc.Item1, nxt));
Console.Write(result);
"[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]" - входные данные отсортированы или это пример такой неудачный?
Если отсортированы, то можно подойти к решению задачи аналитически, и всё упрощается:
using System;
using System.Linq;
static class Program {
static void Main() {
var nums = Console.ReadLine().Split(',').Select(s => int.Parse(s)).ToArray();
Console.WriteLine(nums.Length - nums.Distinct().Count());
}
}
Количество серий из подряд идущих одинаковых чисел равно разнице общего количества чисел и количества уникальных чисел. Если в массиве из N чисел число одно, то количество серий, очевидно, равно N-1, потому что первое число не даёт серию. Каждое новое число уменьшает количесво серий на 1, отсюда и решение.
Если не отсортированы, то тогда я бы сделал так:
using System;
using System.Linq;
static class Program {
static void Main() {
var nums = Console.ReadLine().Split(',').Select(s => int.Parse(s)).ToArray();
int q = 0, k = nums.Length;
for (int i = 1, j = nums[0]; i < k; j = nums[i++]) if (nums[i] == j) q++;
Console.WriteLine(q);
}
}