#arrays #matlab #for-loop #sum
#массивы #matlab #для цикла #сумма
Вопрос:
Предположим, у меня есть массив длиной 15
x = randi([0 5], 1,15);
Я хочу суммировать все 3 элемента x
вместе и поместить каждую сумму в новый массив с именем y
, как показано ниже:
y = [y1 y2 y3 y4 y5];
Пожалуйста, помогите мне сделать это в Matlab, используя циклы for.
Ответ №1:
Вот векторизованный подход, который автоматически обрабатывает возможный меньший последний фрагмент:
x = randi([0 5], 1, 15); % example data
N = 3; % chunk size
y = accumarray(ceil((1:numel(x))/N).', x(:));
Комментарии:
1. Не могли бы вы показать использование циклов for, поскольку это требование
2. @Raykh Я не видел этого требования в вашем вопросе, извините. В любом случае, теперь у вас есть ответы из трех
for
циклов
Ответ №2:
вы можете использовать reshape
следующим образом:
y = sum(reshape(x,3,[]))
Это преобразует ваш вектор x
в массив 3 на все, что осталось, затем суммирует по правильному измерению…
В случае, если количество элементов, которые вы хотите суммировать, не соответствует общей длине вектора, вы можете дополнить нулями или NaN в конце, чтобы это сработало. Здесь я выбрал добавление нулей:
x = randi([0 5], 1,15);
n = 4 ; % sum every n elements (which is the number of rows in the reshape)
try
y = sum(reshape(x, n, []));
catch
disp('added trailing zeros!')
x(numel(x) (n - mod(numel(x), n))) = 0;
y = sum(reshape(x, n, []));
end
(вы можете сделать это с условием if вместо этого, мне просто нравится пытаться поймать больше здесь)
Комментарии:
1. не могли бы вы показать мне, как реализовать с помощью циклов for, пожалуйста
2. Использование
try
/catch
здесь довольно плохая практика (и ненужная), вы заранее знаете, с какой проблемой пытаетесь справиться, поэтому обрабатывайте ее, не вызывая ошибок! Разве захваченный случай не обработал бы его независимо, сделав начальныйtry
избыточным?3. @bla, я использовал функцию reshape, чтобы преобразовать массив в матрицу размером 5X3, затем использовал 2 (вложенных) цикла for для итерации по матрице и суммирования.
4. @Wolfie, я закончил свой ответ, что это можно сделать с условием if… это вопрос предпочтения для этого ответа, мы не отвечаем на более важный вопрос о стиле кода и т.д.
Ответ №3:
Использование for
циклов:
y = zeros(1,5);
for i = 1:5
idx = (i-1)*3 1:(i-1)*3 3;
y(i) = sum(x(idx));
end
Комментарии:
1. как это возможно? в цикле у вас будет неположительное целое число, а Matlab так не работает.
2. Почему вы так думаете? Если вы ссылаетесь на
idx
, он всегда возвращает целые числа от 1 до 15 (для данного случая). Вы могли бы переписать это какidx = (i-1)*3 (1:3)
, если это поможет вам понять это: на первой итерации,i = 1
такidx = (1-1)*3 (1:3) = 1:3
и так далее.
Ответ №4:
Используя ссылочную переменную Target
, которая используется для указания начальной позиции каждого раздела, можно выполнить приведенный ниже цикл. Если вы хотите использовать только циклы, можно выполнить альтернативный внутренний цикл. Этот метод работает почти на том же уровне, что и оконный.
Метод 1: одиночный цикл For с индексацией
x = randi([0 5], 1,15);
y = zeros(1,length(x)/3);
Index = 1;
for Target = 1: 3: 15
Partition = x(Target:Target 2);
y(1,Index) = sum(Partition);
Index = Index 1;
end
Метод 2: Внешние и внутренние циклы For
x = randi([0 5], 1,15);
y = zeros(1,length(x)/3);
Partition = zeros(1,3);
Index = 1;
for Target = 1: 3: 15
for Column = 1: 1: 3
Partition(1,Column) = x(1,Target Column-1);
end
y(1,Index) = sum(Partition);
Index = Index 1;
end