我有一个坐标列表(x,y),我需要找到列表中每个坐标的第一个和最后一个出现的索引。示例(在我的use-cast中我有~30M坐标):
x = [1 3 7 1 3];y = ……
假设坐标是正整数,特别是当坐标范围很小时,你可以使用 accumarray :
accumarray
x1 = min(x); y1 = min(y); x2 = max(x); y2 = max(y); sz = [y2-y1+1, x2-x1+1]; ind = sub2ind(sz,y-y1+1, x-x1+1); ifirst = accumarray(ind(:), 1:numel(ind), [], @min); ilast = accumarray(ind(:), 1:numel(ind), [], @max); Mfirst = ifirst(ind); Mlast = ilast(ind);
对于更高的范围,您可以使用稀疏选项:
ifirst = accumarray(ind(:), 1:numel(ind), [], @min,[],1); ilast = accumarray(ind(:), 1:numel(ind), [], @max,[],1);
该 unique 功能可以做到这一点:
unique
[~, b, c] = unique([x(:) y(:)], 'rows', 'first'); first = b(c).'; [~, b, c] = unique([x(:) y(:)], 'rows', 'last'); last = b(c).';
如果你有30M点,那么你可能没有足够的内存用于这种方法......但对于较小的阵列来说它很快
x = [1 3 7 1 3]; y = [5 1 6 5 1]; xy = cat( 3, x, y ); chk = all( xy == permute( xy, [2 1 3] ), 3 ); [~,first] = max( chk ); [~,last] = max( flipud( chk ) ); last = size(chk,1) - last + 1;
的 编辑 强> 你也可以这样做 findgroups ,循环遍历唯一的坐标而不是每个坐标,以便有一个可能更短的循环......
findgroups
x = [1 3 7 1 3]; y = [5 1 6 5 1]; g = findgroups( x, y ); first = zeros( size( x ) ); last = first; for ii = 1:max(g) idx = (ii==g); first( idx ) = find( idx, 1, 'first' ); last( idx ) = find( idx, 1, 'last' ); end
的 EDIT2 强> 我认为这些相对于其他答案都相当慢......