关于矩阵操作的问题

时间:2011-01-14 10:00:03

标签: arrays algorithm matlab indexing matrix

给定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 个答案:

答案 0 :(得分:7)

如果你想在Matlab的数组'tab'中出现第一个值4次,你可以使用

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

答案 1 :(得分:2)

这是我的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

接下来,我们在result矩阵上调用CUMSUM来计算沿行的累积和。每行将告诉我们到目前为止所讨论的元素出现了多少次:

>> 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}}表示我们要查找的元素的索引。在这种情况下,它是第三行(1),因此唯一向量中的第三个元素是答案r=3。请注意,如果我们在原始数组中重复了4次或更多次元素,那么第一次出现的元素将首先在上面的表达式中逐列显示为val = n(r)

查找相应答案值的索引是对FIND的简单调用......

答案 2 :(得分:0)

这是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;

答案 3 :(得分:0)

忽略这一点并使用Amro的强大解决方案。 。 。

以下是我在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')

答案 4 :(得分:0)

由于我无法轻易理解某些解决方案,因此我做了一个:

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

我发现这更容易想象。它填补了&#39; 1&#39;在方阵的所有位置,其中数组中的值存在 - 根据它们的位置(行)和值(列)。这可以很容易地总结并映射到原始数组。缺点:如果数组包含非常大的值,A也可能相对较大。

答案 5 :(得分:0)

你的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)