самые элегантные решения (то есть те, без использования итераций find
) включают замены входов до ismember
и группировки, как индексы с accumarray
, как в ответе Эйтана, или векторизации поиска с bsxfun
, как и в ответе Луиса Мендо, ИМХО.
Однако для тех, кто заинтересован в растворе с незарегистрированной функциональностью, и по общему признанию хака подхода, здесь это еще один способ сделать это (то есть для каждого элемента A
, найти индексы всех соответствующих элементов в B
). Мысль выглядит следующим образом: в отсортированном B
, что, если у вас были первые и последние индексы каждого соответствующего элемента?Оказывается, есть две вспомогательные функции, используемые ismember
(если у вас есть R2012b +, я думаю), что даст вам оба этих показателя: _ismemberfirst
(a builtin
) и ismembc2
.
Для примера данных A = [5 3 4 2]; B = [2 4 4 4 6 8];
в вопросе, здесь реализация:
[Bs,sortInds] = sort(B); % nop for this B, but required in general
firstInds = builtin('_ismemberfirst',A,Bs) % newish version required
firstInds =
0 0 2 1
lastInds = ismembc2(A,Bs)
lastInds =
0 0 4 1
Тяжелая атлетика это делается сейчас - у нас есть первые и последние индексы в B
для каждого элемента в A
без необходимости делать петли. Не существует A(1)
или A(2)
(5 или 3) в B
, поэтому эти индексы 0
. Значение 4 (A(3)
) происходит в местах 2: 4 (то есть all(B(2:4)==A(3))
). Аналогично, A(4)
находится по адресу B(1:1)
.
Мы можем игнорировать sortInds
в приведенном выше примере, так как B
уже отсортированы, но несортированный B
обрабатываются просто глядя на места в несортированном массиве. Мы можем быстро сделать этот поиск и упаковать каждый диапазон индексов с arrayfun
, имея в виду, что объем вычислений задача на самом деле нахождения индексов уже сделано:
allInds = arrayfun(@(x,y)sortInds(x:y-(x==0)),firstInds,lastInds,'uni',0)
allInds =
[1x0 double] [1x0 double] [1x3 double] [1]
Каждая ячейка имеет индексы в B
(если таковые имеются) каждого элемента A
. Первые две ячейки представляют собой пустые массивы, как и ожидалось. Приглядевшись на третьем элементе:
>> allInds{3}
ans =
2 3 4
>> A(3)
ans =
4
>> B(allInds{3})
ans =
4 4 4
операция Тестирование с несортированным B
:
B(4:5) = B([5 4])
B =
2 4 4 6 4 8
[Bs,sortInds] = sort(B);
firstInds = builtin('_ismemberfirst',A,Bs);
lastInds = ismembc2(A,Bs);
allInds = arrayfun(@(x,y)sortInds(x:y-(x==0)),firstInds,lastInds,'uni',0);
allInds{3} % of A(3) in B
ans =
2 3 5
B(allInds{3})
ans =
4 4 4
Стоит ли делать это таким образом, со штрафом за sort
и два эффективных ismember
звонков? Возможно, нет, но я думаю, что это интересное решение. Если у вас есть отсортированный B
, он еще быстрее, так как две встроенные функции предполагают, что второй аргумент (Bs
) сортируется и не тратит время на проверки. Попытайтесь посмотреть, что сработает для вас.
Вы просмотрели любой из предложенных ответов? Если вы обнаружили, что кто-либо из них полезен, пожалуйста, рассмотрите их и, возможно, пометьте один из них, как принято. –
@ user3077261 У вас есть несколько хороших ответов здесь, как сказал Эйтан. Повысьте любые ответы, которые вы найдете полезными и/или предложите рабочее решение, а затем посмотрите, что вам больше всего нравится в вашей проблеме и принимайте (установите флажок). – chappjc