Зубчатые массивы и LINQ

402
10 сентября 2021, 16:10

Задание:
В каждой нечетной строке ступенчатой матрице найти произведение элементов. Выбрать отрицательные и посчитать их количество, если отрицательных нет вывести -1.
Допустим есть массив:

int[][] numbers = new int[3][];
numbers[0] = new int[] { 3, 2 };
numbers[1] = new int[] { 1, 2, 3 };
numbers[2] = new int[] { 1, 2, 3, 4, 5 };

Например я хочу проверить все ли элементы больше нуля
Вот код для одномерных массивов:

if (numbers.All(x => x > 0))
    Console.WriteLine("Все элементы больше нуля");

Как будет выглядеть код для ступенчатых массивов? И как к ним правильно обращаться?

Answer 1
  1. В каждой нечетной строке ступенчатой матрице найти произведение элементов.

    int[] result = (numbers.Select(x => Array.IndexOf(numbers, x) % 2 != 0
        ? x.Aggregate((first, item) => first * item) : -1))
        .Where(x => x != -1)
        .ToArray();
    

    Вывод: 6.

  2. Выбрать отрицательные и посчитать их количество, если отрицательных нет вывести -1.

    int answer = numbers.Sum(x => x.Count(y => y > 0)) == numbers.Sum(x => x.Count())
        ? -1 : numbers.Sum(x => x.Count(y => y < 0));
    

    Вывод: -1 по вашему примеру

  3. Для ступенчатого массива

    if (numbers.All(x => x.All(y => y > 0))
    
Answer 2

Как-то непривычно использовать для подобных задач LiNQ, но должен признать, что получилось немного более читабельно, чем на обычных циклах, правда на счет производительности не уверен, для олимпиад и задач критичных ко времени выполнения применять бы не стал, но разница должна быть невелика на малом объеме данных, особенно с учетом низкой скорости вывода в консоль.

numbers
    .Where((row, idx) => idx % 2 == 0)//выбираем нечетные строки в естественном порядке (четные индексы)
    .Select(row =>//собираем результат из данных строки
         row.Any(x => x < 0)//если хоть один элемент меньше 0
         ? row.Aggregate((x,y) => x * y)//берем произведение
         : -1)//иначе -1
    .ToList()//для следующей операции получаем List<int>
    .ForEach(val => Console.WriteLine(val));

Если подключить NuGET-пакет MoreLINQ или самостоятельно дописать метод-расширение ForEach для IEnumerable<T> (штатно он предусмотрен только для List<T>), то можно избавиться от ToList(), что позволит использовать немного меньше памяти и чуть-чуть улучшить производительность за счет отсутствия выделения памяти под List и заполнение его данными:

numbers
    .Where((row, idx) => idx % 2 == 0)//выбираем нечетные строки в естественном порядке (четные индексы)
    .Select(row =>//собираем результат из данных строки
         row.Any(x => x < 0)//если хоть один элемент меньше 0
         ? row.Aggregate((x,y) => x * y)//берем произведение
         : -1)//иначе -1
    .ForEach(val => Console.WriteLine(val));
READ ALSO
Gravity Scale 2D

Gravity Scale 2D

В компоненте Rigidbody2D есть такой параметр как Gravity Scale каким образом он влияет на глобальный компонент гравитации? Те

141
Unity. Использование кнопки &quot;Назад&quot; для вызова метода

Unity. Использование кнопки "Назад" для вызова метода

Можно ли обойтись без методов типа Update что бы заставить кнопку "назад" вызывать какой либо метод? Хотелось бы обойтись без постоянного вызова...

109
Десятичные числа MS ACCESS C#

Десятичные числа MS ACCESS C#

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

418