Вопрос о матричной манипуляции - PullRequest
5 голосов
/ 14 января 2011

Учитывая матрицу 1 * N или массив, как мне найти первые 4 элемента, которые имеют одинаковое значение, а затем сохранить индекс для этих элементов?

PS: Мне просто любопытно.Что, если мы хотим найти первые 4 элемента, значения которых находятся в определенном диапазоне, скажем, ниже 2?Например, M = [10,15,14.5,9,15.1,8.5,15.5,9.5], элементы, которые я ищу, будут 15,14,5,15,1,15,5, а индексы будут 2,3,5,7.

Ответы [ 6 ]

7 голосов
/ 14 января 2011

Если вы хотите, чтобы первое значение присутствовало 4 раза в массиве 'tab' в Matlab, вы можете использовать

num_min = 4
val=NaN;
for i = tab
    if sum(tab==i) >= num_min
        val = i;
        break
    end
end
ind = find(tab==val, num_min);

По экземпляру с

tab = [2 4 4 5 4 6 4 5 5 4 6 9 5 5]

вы получите

val =
     4
ind =
     2     3     5     7
2 голосов
/ 14 января 2011

Вот мое решение MATLAB:

array = randi(5, [1 10]);            %# random array of integers

n = unique(array)';                  %'# unique elements
[r,~] = find(cumsum(bsxfun(@eq,array,n),2) == 4, 1, 'first');
if isempty(r)
    val = []; ind = [];              %# no answer
else
    val = n(r);                      %# the value found
    ind = find(array == val, 4);     %# indices of elements corresponding to val
end

Пример:

array =
     1     5     3     3     1     5     4     2     3     3
val =
     3
ind =
     3     4     9    10

Пояснение:

Прежде всего, мы извлекаем список уникальных элементов. В приведенном выше примере мы имеем:

n =
     1
     2
     3
     4
     5

Затем, используя функцию BSXFUN, мы сравниваем каждое уникальное значение со всем имеющимся у нас векторным массивом. Это эквивалентно следующему:

result = zeros(length(n),length(array));
for i=1:length(n)
    result(i,:) = (array == n(i));        %# row-by-row
end

Продолжая с тем же примером, мы получим:

result =
     1     0     0     0     1     0     0     0     0     0
     0     0     0     0     0     0     0     1     0     0
     0     0     1     1     0     0     0     0     1     1
     0     0     0     0     0     0     1     0     0     0
     0     1     0     0     0     1     0     0     0     0

Затем мы вызываем CUMSUM для матрицы result, чтобы вычислить накопленную сумму по строкам. В каждой строке будет указано, сколько раз данный элемент появлялся до сих пор:

>> cumsum(result,2)
ans =
     1     1     1     1     2     2     2     2     2     2
     0     0     0     0     0     0     0     1     1     1
     0     0     1     2     2     2     2     2     3     4
     0     0     0     0     0     0     1     1     1     1
     0     1     1     1     1     2     2     2     2     2

Затем мы сравним это с четырьмя cumsum(result,2)==4 (поскольку нам нужно место, где элемент появился в четвертый раз):

>> cumsum(result,2)==4
ans =
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     1
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0

Наконец, мы вызываем FIND для поиска первого появления 1 в соответствии с порядком столбцов: если мы перебираем матрицу из предыдущего шага столбец за столбцом, то строка первого появления 1 указывает Индекс элемента, который мы ищем. В данном случае это была третья строка (r=3), поэтому третьим элементом в уникальном векторе является ответ val = n(r). Обратите внимание, что если у нас было несколько элементов, повторенных 4 или более раз в исходном массиве, то первый, появившийся в четвертый раз, сначала будет отображаться как 1 столбец за столбцом в приведенном выше выражении.

Поиск индексов соответствующего значения ответа - это простой вызов FIND ...

0 голосов
/ 15 января 2011

Ты PS вопрос сложнее.У меня не было времени проверить каждый случай, но идея здесь:

M=[10,15,14.5,9,15.1,8.5,15.5,9.5]
val = NaN;
num_min = 4;
delta = 2;
[Ms, iMs] = sort(M);
dMs = diff(Ms);
ind_min=Inf;
n = 0;
for i = 1:length(dMs)
    if dMs(i) <= delta
    n=n+1;
    else
    n=0;
    end
    if n == (num_min-1)
        if (iMs(i) < ind_min)
            ind_min = iMs(i);
        end
    end
end
ind = sort(iMs(ind_min + (0:num_min-1)))
val = M(ind)
0 голосов
/ 14 января 2011

Поскольку я не мог легко понять некоторые из решений, я сделал это:

l = 10; m = 5; array = randi(m, [1 l])

A = zeros(l,m);    % m is the maximum value (may) in array
A(sub2ind([l,m],1:l,array)) = 1;
s = sum(A,1);
b = find(s(array) == 4,1); 
% now in b is the index of the first element

if (~isempty(b)) 
    find(array == array(b))
else 
    disp('nothing found'); 
end

Мне легче это визуализировать. Он заполняет «1» во всех местах квадратной матрицы, где существуют значения в массиве - в соответствии с их положением (строка) и значением (столбец). Это легко суммируется и сопоставляется с исходным массивом. Недостаток: если массив содержит очень большие значения, A может также стать относительно большим.

0 голосов
/ 14 января 2011

Игнорируйте это и используйте могущественное решение Амро.,,

Вот как я это сделаю в Matlab.Матрица может быть любого размера и содержать любой диапазон значений, и это должно работать.Это решение автоматически найдет значение, а затем признаки первых 4 элементов, не передавая значение поиска априори.

tab = [2 5 4 5 4 6 4 5 5 4 6 9 5 5]

%this is a loop to find the indicies of groups of 4 identical elements
tot = zeros(size(tab));
for nn = 1:numel(tab)
    idxs=find(tab == tab(nn), 4, 'first');
    if numel(idxs)<4
        tot(nn) = Inf;
    else
        tot(nn) = sum(idxs);
    end        
end

%find the first 4 identical
bestTot = find(tot == min(tot), 1, 'first' );

%store the indicies you are interested in.
indiciesOfInterst = find(tab == tab(bestTot), 4, 'first')
0 голосов
/ 14 января 2011

Вот код C ++

std::map<int,std::vector<int> > dict;

std::vector<int> ans(4);//here we will store indexes
bool noanswer=true;

//my_vector is a vector, which we must analize
for(int i=0;i<my_vector.size();++i)
{
    std::vector<int> &temp = dict[my_vector[i]];
    temp.push_back(i);
    if(temp.size()==4)//we find ans
    {
         std::copy(temp.begin(),temp.end(),ans.begin() );
         noanswer = false;
         break;
    }   
}
if(noanswer)
   std::cout<<"No Answer!"<<std::endl;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...