Я работаю с Matlab.
У меня есть двоичная квадратная матрица. Для каждой строки есть одна или несколько записей 1. Я хочу просмотреть каждую строку этой матрицы и вернуть индекс этих 1 и сохранить их в записи ячейки.
Мне было интересно, есть ли способ сделать это без циклического прохождения по всем строкам этой матрицы, так как цикл for действительно медленный в Matlab.
Например, моя матрица
M = 0 1 0
1 0 1
1 1 1
Тогда в конце концов, я хочу что-то вроде
A = [2]
[1,3]
[1,2,3]
Так A
и клетка.
Есть ли способ достичь этой цели без использования цикла for с целью более быстрого вычисления результата?
matlab
vectorization
ftxx
источник
источник
for
циклов? Для этой проблемы, с современными версиями MATLAB, я сильно подозреваю, чтоfor
цикл является самым быстрым решением. Если у вас есть проблемы с производительностью, я подозреваю, что вы ищете не то место для решения, основанного на устаревших советах.cellfun
.1
в типичном ряду? Я не ожидал бы, чтоfind
цикл займет что-то около 30 с для чего-то достаточно маленького, чтобы поместиться в физической памяти.Ответы:
Внизу этого ответа приведен код тестирования, поскольку вы пояснили, что вы заинтересованы в производительности, а не в том, чтобы произвольно избегать
for
циклов.На самом деле, я думаю, что
for
циклы, вероятно, наиболее эффективный вариант здесь. Поскольку был введен «новый» (2015b) механизм JIT ( циклы источника )for
не являются изначально медленными - фактически они оптимизируются внутренне.Из теста видно, что
mat2cell
опция, предлагаемая ThomasIsCoding здесь , очень медленная ...Если мы избавимся от этой линии, чтобы сделать шкалу более четкой, то мой
splitapply
метод будет довольно медленным, опция accmarray в obchardon немного лучше, но самые быстрые (и сопоставимые) варианты используют либоarrayfun
(как это было предложено Томасом), либоfor
цикл. Обратите внимание , чтоarrayfun
в основномfor
петля замаскированный для большинства сценариев использования, так что это не удивительно , галстук!Я бы порекомендовал вам использоватьfor
цикл для повышения читабельности кода и лучшей производительности.Редактировать :
Если мы предположим, что цикл является самым быстрым подходом, мы можем сделать некоторые оптимизации вокруг
find
команды.конкретно
Сделай
M
логичным. Как показано на графике ниже, это может быть быстрее для относительно небольшихM
, но медленнее с компромиссом преобразования типов для большихM
.Используйте логический
M
для индексации массива1:size(M,2)
вместо использованияfind
. Это позволяет избежать самой медленной части цикла (find
команды) и перевешивает накладные расходы при преобразовании типов, что делает его самым быстрым вариантом.Вот моя рекомендация для лучшей производительности:
Я добавил это к тесту ниже, вот сравнение подходов в стиле цикла:
Код бенчмаркинга:
источник
M
. Например, если заполнено только 5% элементов,M = randi([0,20],N) == 20;
тоfor
цикл является самым медленным и вашarrayfun
метод выигрывает.accumarray
безind2sub
, но он медленнее, чемfor
циклВы можете попробовать,
arrayfun
как показано ниже, которые охватывают рядыM
или (более медленный подход
mat2cell
)источник
arrayfun
это в основном замаскированная петля, поэтому она может потерпеть неудачу на обоих фронтах: 1) избегать петель и 2) быть быстрыми, на что надеялся ОПРедактировать : я добавил тест, результаты показывают, что цикл for более эффективен, чем
accumarray
.Вы можете использовать
find
иaccumarray
:Матрица транспонирована (
A'
), потому чтоfind
группируется по столбцу.Пример:
Вывод:
Ориентир:
Результат:
Цикл for более эффективен, чем
accumarray
...источник
Используя accmarray :
источник
MM{I} = find(M(I, :))
.ind2sub
:[ii, jj] = find(M); accumarray(ii, jj, [], @(x){x})
Вы можете использовать strfind :
источник
string
типов, а не символов? Есть много оптимизаций для строк, поэтому они существуют ...