2017-02-20 12 views
1

Конкретная задача, которую я пытаюсь достичь, это трудно описать, так вот пример: дано А и хСравнивая только ненулевые элементы

A = [1 2; 
    3 0; 
    3 5; 
    4 0]; 

x = [1 2 3]; 

Я хочу, чтобы алгоритм для вывода

output: [1 2] 

что все ненулевые элементы в строках 1 и 2 в A находятся в x.

Я сделал это с использованием массивов ячеек и петель; однако A и x очень велики, и мой подход вовсе не эффективен. Кроме того, я не могу понять, как переработать, чтобы дать мне то, что я хочу. Каков наиболее быстрый метод с наименьшей интенсивностью памяти?

EDIT: Извинения, мой оригинальный пример был слишком упрощенным. Теперь это исправлено.

ответ

4

Первый ответ хороший, но я бы порекомендовал до не используя arrayfun. Есть более красноречивые способы делать то, что вы просите. Используйте ismember в сочетании с all, затем проиндексируйте в матрицу A, когда закончите. В основном, ваша проблема заключается в том, чтобы определить, имеет ли строка все значения, найденные в x, и игнорирование нулевых значений. В этом случае мы можем найти все значения в матрице A, которые фактически равны нулю, а затем использовать это для увеличения нашего результата.

Использование A как первый вход и x как второй вход возвращает матрицу того же размера, как и A, что говорит вам, является ли элемент в A находится в x. Если вы хотите проверить, есть ли все элементы в матрице A для строки в x, проверьте, все элементов в строке 1. Кроме того, найдите все элементы, которые равны нулю, затем с выходом ismember установите их равными 1. Это можно сделать с помощью logical OR. После этого вы можете использовать all и проверить каждую строку независимо, используя вывод ismember в качестве первого ввода в all и установив второй аргумент в 2. Затем будут возвращены все строки в матрице A, где любой столбец находится в xигнорируя любые значения, которые равны нулю для строки в A что то, что вы ищете:

A = [1 2; 3 0; 4 0]; 
x = [1 2 3]; 
mask = ismember(A, x); 
ind = all(mask | A == 0, 2); 

Я также в пользу острот.Мы можем объединить это в одну строку кода:

ind = all(ismember(A, x) | A == 0, 2); 

Даже короче просто инвертировать A. Все нулевые элементы становятся true и false иначе:

ind = all(ismember(A, x) | ~A, 2); 

ind бы, таким образом:

>> ind 

ind = 

    3×1 logical array 

    1 
    1 
    0 

Так как вы хотите, фактические индексы строк, вы можете просто использовать find на вершине этого:

>> find(ind) 

ans = 

    1 
    2 

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

>> A = [1 2;3 5;4 0]; 
>> x = [1 2 3]; 
>> ind = all(ismember(A, x) | ~A, 2) 

ind = 

    3×1 logical array 

    1 
    0 
    0 

>> find(ind) 

ans = 

    1 
+0

Я думаю, что это просто выводит первую строку A, а не индексы строк 1 и 2. – jonem

+0

@jonem А вы хотите индексы строк? Хорошо, позвольте мне изменить. – rayryeng

+0

Да, мне было тяжело, потому что вся функция возвращает нуль для строки 2 из-за нулевого элемента в элементе (2,2), хотя я не хочу включать элемент (2,2) в сравнении. – jonem

3

Я думаю, что лучший способ переработать ismember - убедиться, что нет никаких «членов», просто проверяя ненулевые элементы в A. arrayfun может быстро выполнить работу. Он использует наиболее эффективные параллельные вычисления для вашей конкретной машины. Следующая строка должна вернуть правильный результат:

find(arrayfun(@(a) sum(~ismember(A(a,A(a,:)>0),x)),1:size(A,1))==0) 

Это вы искали?

Однако, если ваша проблема связана с памятью, вам может потребоваться разбить операцию arrayfun на куски (1: пол (размер (A, 1)/2), пол (размер (A, 1)/2): размер (A, 1) или меньшие куски), так как MATLAB ставит кучу работников для выполнения задачи и может использовать всю имеющуюся оперативную память ...

+0

Спасибо за ответ, знаете ли вы, как это сравнивается с петлей с точки зрения эффективности? – jonem

+0

Я думаю, что он сравнивается с парфором с наилучшей конфигурацией. Эффективность зависит от параллельной емкости вашей конкретной машины ... Вы можете выполнить быстрый тест с использованием cputime для этой версии, а цикл for (для 1: размер (A, 1) с суммой (blabla) входит внутрь) , – ana

+0

У меня есть голос, когда вы правильно ответили на вопрос правильно. Мне пришлось переделать его 3 раза, чтобы понять это правильно: P – rayryeng