До этого момента мы пользовались срезами, которые выделяли подмножество значений из одномерного массива. Но как быть с двумерными или трехмерными массивами? Для этого придуманы обобщенные срезы, да, именно эти срезы выделяют подмножество из n
-мерных массивов. Как и обычные срезы, обобщенные срезы принимают три параметра, которые определяют параметры среза. Однако, в обобщенных срезах второй и третий параметры задаются массивом. То есть размер подмножества и шаг задаются как массивы, смотрим пример:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20-исходный массив
Параметры обобщенного среза:
- начальный индекс: 0;
- количество элементов: {3, 2}
- размер шага: {7, 5}
Полученный результат:
- 0 5
- 7 13
- 14 19
Итак, каким же образом у нас получился такой результат? Во-первых, исходный массив всегда является одномерным массивом, полученный массив также является одномерным, хотя я его представил как двумерный. Это было сделано для более удобного восприятия результата среза. По сути результат был бы таким — 0 5 7 13 14 19, но такой вид массива труден к восприятию.
Вернемся к параметрам среза. С первым параметром среза все ясно, так же как и в простых срезах, первый параметр указывает на первый элемент выборки. Второй параметр среза — это количество элементов, которые попадут в подмножество, оно задается массивом. В нашем примере указаны числа 3 и 2, значит подмножество будет состоять из трех серий в каждой серии два элемента. В итоге, если перемножить эти два числа получится 6 элементов. Собственно в полученном результате мы видим три строки, два столбца и элементов всего — 6.
Перейдем к третьему параметру среза — это шаг выборки, и он также задается массивом. В массиве указаны два числа: 7 и 5. Что это значит? Число 7 — это шаг между сериями подмножества. Число пять — это шаг между элементами в одной серии. По результату это хорошо видно.
Вот еще один пример среза:
- индекс: 2;
- размер подмножества: {2, 6}
- шаг: {4, 10}
Полученное подмножество:
- 2 12 22 32 42 52
- 6 16 26 36 46 56
Как видите, тут мы получили 2 серии по 6 элементов, серии разделены расстоянием в 4 элемента. В одной серии между элементами расстояние 10. В этом примере я также из полученного подмножества собрал двухмерный массив. На самом же деле получится такой набор элементов: 2 6 12 16 22 26 32 36 42 46 52 56. Как видите, в этом примере числа из двух серий смешаны, это связано с тем, что шаг между сериями меньше шага между элементами одной серии. Давайте рассмотрим пример программы, в которой используются обобщенные срезы:
#include <iostream> #include <valarray> // заголовочный файл массивов значений #include <iomanip> using namespace std; int main() { valarray<int> array(0, 60); // определяем массивы обобщенного среза size_t length[] = {2, 6}; // две серии, в каждой серии по 6 элементов size_t stride[] = {4, 10}; // шаг между сериями - 4 элемента, шаг между элементами одной серии - 10. // создаем два объекта, в которые помещаем массивы срезов valarray<size_t> len(length, 2); valarray<size_t> str(stride, 2); array[gslice(2, len, str)] = 1; // по срезу присваиваем всем элементам подмножества единицу cout << "Измененный массив значений: "; for(int i = 0; i < array.size(); i++) { cout << array[i] << " "; } cout << "\nПодмножество(индексы элементов массива): "; for(int i = 0, j = 0; i < array.size(); i++, j++) { if ( array[i] == 1) { cout << setw(2) << i << " "; } } return 0; }
Результат:
Измененный массив значений: 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 Подмножество(индексы элементов массива): 2 6 12 16 22 26 32 36 42 46 52 56
Просто, чтобы уточнить, в этой программе задан срез из предыдущего примера. В строках 11-12 определены массивы, которые далее в программе будут использоваться для указания второго и третьего параметров среза. Кроме того, типы данных этих массивов должны быть size_t
. Так как во второй и третий параметры среза передаются массивы, последние должны иметь тип данных valarray
, поэтому переводим массивы из строк 11-12 в valarray, строки 15-16. Теперь когда массивы полностью готовы, мы их передаем в функцию обобщенного среза gslice
, строка 18.
Обратите внимание, что у функции обобщенного среза немного другое имя. Еще, в строке 18 каждому элементу подмножества присваиваем 1. Ну и в конце программы, в строках 26 — 30 мы выводим индексы элементов подмножества, это тоже видно в результате.
Еще хочу обратить ваше внимание на то, что срезы можно задавать n
-мерные. Мы создавали пока только двухмерные подмножества. Если хотите трехмерное подмножество просто добавте в массивы срезов еще по одному значению, например, так:
size_t length[] = {2, 6, 4}; size_t stride[] = {4, 10, 3};
Тогда у вас получится срез с тремя измерениями, но запомните, что количество элементов в массивах среза должно быть одинаковым, иначе получите подобную ошибку:
Это была не простая темя для изучения, советую вам поэкспериментировать немного с моей программой, для более лучшего понимания этой темы. Далее мы приступим к изучению масок для срезов.
Комментарии
TonyVCLCSA .
valarray<
size_t
> len(length, 2);
Здесь 2 это sizeof(length) / sizeof(length[0]).
Это объяснялось в теме по массивам значений.
Но у меня с ним не работает, зато если инициализирую без 2, то все работает. Может это особенность sololearn на а андроид, а может чтото поменялось. Судя по комментариям, статье 2 года минимум.
Vova Denys
luda
В первом примере, в «Полученный результат:» вместо «7 13″ должно быть 7 12.
blablabla
ничего непонятно.
как массив записан в другой массив, и что значит в строках 15-16 цифра 2?
Vova Denys