Замените повторяющееся значение на основе размера последовательности — Matlab

У меня есть 2D-матрица, состоящая из единиц и нулей.

mat = [0 0 0 0 1 1 1 0 0
       1 1 1 1 1 0 0 1 0
       0 0 1 0 1 1 0 0 1];

Мне нужно найти все последовательные повторения единиц в каждой строке и заменить все единицы нулями Только, когда размер последовательности меньше 5 (5 последовательных):

mat = [0 0 0 0 0 0 0 0 0
       1 1 1 1 1 0 0 0 0
       0 0 0 0 0 0 0 0 0];

Любое предложение о том, как подойти к этой проблеме, будет очень кстати.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
34
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать diff, чтобы найти начальную и конечную точки прогонов 1, и некоторую логику, основанную на этом, чтобы обнулить слишком короткие прогоны. См. приведенный ниже код с соответствующими комментариями.

% Input matrix of 0s and 1s
mat = [0 0 0 0 1 1 1 0 0
       1 1 1 1 1 0 0 1 0
       0 0 1 0 1 1 0 0 1];
% Minimum run length of 1s to keep   
N = 5;

% Get the start and end points of the runs of 1. Add in values from the
% original matrix to ensure that start and end points are always paired
d = [mat(:,1),diff(mat,1,2),-mat(:,end)];
% Find those start and end points. Use the transpose during the find to
% flip rows/cols and search row-wise relative to input matrix.
[cs,r] = find(d.'>0.5);  % Start points
[ce,~] = find(d.'<-0.5); % End points
c = [cs, ce];            % Column number array for start/end
idx = diff(c,1,2) < N;   % From column number, check run length vs N

% Loop over the runs which didn't satisfy the threshold and zero them
for ii = find(idx.')
    mat(r(ii),c(ii,1):c(ii,2)-1) = 0;
end

Если вы хотите выбросить читаемость из окна, это можно сжать для немного более быстрой и плотной версии, основанной на той же логике:

[c,r] = find([mat(:,1),diff(mat,1,2),-mat(:,end)].'); % find run start/end points
for ii = 1:2:numel(c)     % Loop over runs
    if c(ii+1)-c(ii) < N  % Check if run exceeds threshold length
        mat(r(ii),c(ii):c(ii+1)-1) = 0; % Zero the run if not
    end
end

Спасибо, это работает как шарм! Не могли бы вы объяснить причину транспонирования при поиске начальной и конечной точек?

Oiko 09.05.2022 17:00

Конечно, MATLAB обычно работает по столбцам, поэтому я мог бы сделать [r,ce] = find(d>0.5), но значения r (номер строки), например, были бы [2,2,2,3,2,1,2,3,...], поэтому все строки перемешаны, а соседние элементы не соответствуют начало/конец пробега в одном ряду. Однако, переворачивая его (и переворачивая выходные данные из строки/столбца в столбец/строку), мы получаем все индексы столбцов для строки 1, затем для всей строки 2 и т. д. Поскольку я следил за тем, чтобы всегда была парная начальная/ заканчиваются на d, затем их можно сопоставить на [cs,ce] без дальнейшей перетасовки

Wolfie 09.05.2022 17:07

Возможно, был способ избежать более элегантного транспонирования, я не тратил много времени на его поиски, убедившись, что вышеизложенное сработает :)

Wolfie 09.05.2022 17:09

Векторизованное решение @Wolfie красивое и лаконичное, но немного сложное для понимания и далекое от формулировки проблемы. Вот прямой перевод задачи с использованием циклов. Его преимущество в том, что его легче понять, и он немного быстрее с меньшим выделением памяти, что означает, что он будет работать с огромными входными данными.

[m,n] = size(mat);
for i = 1:m
    j = 1;
    while j <= n
        seqSum = 1;
        if mat(i,j) == 1
            for k = j+1:n
                if mat(i,k) == 1
                    seqSum = seqSum + 1;
                else
                    break
                end
            end
            if seqSum < 5
                mat(i,j:j+seqSum-1) = 0;
            end
        end
        j = j + seqSum;
    end
end

У вас есть эталон для "немного быстрее"? Также достаточно легко предлагать дополнительные ответы, не пытаясь ухудшить существующие :)

Wolfie 09.05.2022 22:18

Просто выполните tic .. toc или timeit для широкого диапазона входных данных и сравните результаты. Я вижу около 6% ускорения с большим сокращением памяти в моей версии, потому что она не выделяет временные массивы. Это не имеет ничего общего с вашим решением, у каждого подхода есть свои достоинства и недостатки, это хорошо зарекомендовавшее себя наблюдение. См., например, этот ответ MATLAB и связанный с ними пример в. ..продолжение.

AboAmmar 10.05.2022 05:40

... Я использовал и преподавал MATLAB в течение двух десятилетий и не мог с первого взгляда понять ваше решение. Мой ответ, однако, больше похож на рассказ; просматривайте строки, всякий раз, когда вы находите 1, отслеживайте следующие 1, и если их меньше 5, обнуляйте их. Наконец, это хорошая практика и знания для других языков, таких как C/C++/Julia и т. д.

AboAmmar 10.05.2022 05:40

Другие вопросы по теме