Matlab:找到向量中元素的第一次和最后一次出现?
Matlab: find first and final occurrences of elements in a vector?
我面临着一个不太容易处理的任务。
我有一个包含 4 个一、3 个二、2 个三和 4 个四的矢量图像:
[1,1,1,1,2,2,2,3,3,4,4,4,4]
这意味着我有 1、2、3、4 出现次数不同。
我想找到这些元素的第一个位置和这些元素的最终位置。这意味着我想要:
(1,5,8,10) 作为 第一次出现 of (1,2,3, 4) 在向量中
(4,7,9,13) 作为 (1,2,3, 4) 在向量中
更重要的是,如果参考向量是随机排序而不是排序怎么办?
我知道如何在 unique() 函数的帮助下使用 for 循环来完成它。
我正在寻找针对此类问题的更高效的矢量化解决方案。
感谢您抽出宝贵时间,我们将不胜感激您的帮助。
查看以下代码和示例以及 this 答案:
a = [1,1,1,1,2,2,2,3,3,4,4,4,4];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 5 8 10
last_occurences =
4 7 9 13
a = [2,2,2, 1,1,1,1,4,4,4,4, 3,3];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 4 8 12
last_occurences =
3 7 11 13
a = [4,4,4,4, 1,1,1,1, 3,3, 2,2,2];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 5 9 11
last_occurences =
4 8 10 13
我不确定为什么你不能在没有 for
循环的情况下使用 unique
。仅使用第二个输出,您就可以确定要查找的内容。
以你的例子为例:
A = [1,1,1,1,2,2,2,3,3,4,4,4,4];
如果您想要 A
中每个唯一元素第一次出现的索引,只需这样调用 unique
:
[~,out_first,~] = unique(A, 'first');
此外,如果您想为 A
中的每个唯一元素查找最后一次出现的索引,请这样做:
[~,out_last,~] = unique(A, 'last');
根据你上面的例子,这是我们第一次和最后一次出现的结果:
>> out_first
out_first =
1
5
8
10
>> out_last
out_last =
4
7
9
13
如果您的矢量 A
是随机顺序,unique
仍会找到相对于 A
起始位置的第一个匹配项。例如,如果我打乱 A
:
中的元素
B = A(randperm(numel(A)))
>> B
B =
2 1 4 2 3 2 1 1 1 4 3 4 4
这是我在 运行 unique
上对这个打乱的向量进行处理时得到的结果:
>> out_first
out_first =
2
1
5
3
>> out_last
out_last =
9
6
11
13
如您所见,我们第一次遇到值 1 时,它在索引 2 处,我们第一次遇到值 2 时,它在索引 1 处,依此类推。您可以按照上次遇到的相同模式。
因此,除了对 unique
的单个函数调用之外,我看不出你还能得到多少矢量化。无需使用 for
循环。
x = [1,1,1,1,2,2,2,3,3,4,4,4,4];
s = [1,2,3,4];
[valid, first] = max(bsxfun(@eq, x(:), s(:).'),[],1);
[~, last] = max(bsxfun(@eq, flipud(x(:)), s(:).'),[],1);
first(~valid) = 0;
last = numel(x)-last+1;
last(~valid) = 0;
这利用了这样一个事实,即 max
returns 的第二个输出是每个列中 第一个 最大化器的位置。此外,第一个输出用于确保每个值至少出现一次;如果不是这种情况,则结果将设置为零。因此,例如 s = [1,2,3,4,5]
的结果将是
first =
1 5 8 10 0
last =
4 7 9 13 0
要获得 last 个位置,使用相同的方法,只是使用翻转向量。
每个向量中的元素可以按任意顺序排列。
我面临着一个不太容易处理的任务。
我有一个包含 4 个一、3 个二、2 个三和 4 个四的矢量图像:
[1,1,1,1,2,2,2,3,3,4,4,4,4]
这意味着我有 1、2、3、4 出现次数不同。
我想找到这些元素的第一个位置和这些元素的最终位置。这意味着我想要:
(1,5,8,10) 作为 第一次出现 of (1,2,3, 4) 在向量中
(4,7,9,13) 作为 (1,2,3, 4) 在向量中
更重要的是,如果参考向量是随机排序而不是排序怎么办?
我知道如何在 unique() 函数的帮助下使用 for 循环来完成它。
我正在寻找针对此类问题的更高效的矢量化解决方案。
感谢您抽出宝贵时间,我们将不胜感激您的帮助。
查看以下代码和示例以及 this 答案:
a = [1,1,1,1,2,2,2,3,3,4,4,4,4];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 5 8 10
last_occurences =
4 7 9 13
a = [2,2,2, 1,1,1,1,4,4,4,4, 3,3];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 4 8 12
last_occurences =
3 7 11 13
a = [4,4,4,4, 1,1,1,1, 3,3, 2,2,2];
first_occurences = [1, find(diff([a(1) a a(end)]))]
last_occurences = [first_occurences(2:end) - 1, length(a)]
first_occurences =
1 5 9 11
last_occurences =
4 8 10 13
我不确定为什么你不能在没有 for
循环的情况下使用 unique
。仅使用第二个输出,您就可以确定要查找的内容。
以你的例子为例:
A = [1,1,1,1,2,2,2,3,3,4,4,4,4];
如果您想要 A
中每个唯一元素第一次出现的索引,只需这样调用 unique
:
[~,out_first,~] = unique(A, 'first');
此外,如果您想为 A
中的每个唯一元素查找最后一次出现的索引,请这样做:
[~,out_last,~] = unique(A, 'last');
根据你上面的例子,这是我们第一次和最后一次出现的结果:
>> out_first
out_first =
1
5
8
10
>> out_last
out_last =
4
7
9
13
如果您的矢量 A
是随机顺序,unique
仍会找到相对于 A
起始位置的第一个匹配项。例如,如果我打乱 A
:
B = A(randperm(numel(A)))
>> B
B =
2 1 4 2 3 2 1 1 1 4 3 4 4
这是我在 运行 unique
上对这个打乱的向量进行处理时得到的结果:
>> out_first
out_first =
2
1
5
3
>> out_last
out_last =
9
6
11
13
如您所见,我们第一次遇到值 1 时,它在索引 2 处,我们第一次遇到值 2 时,它在索引 1 处,依此类推。您可以按照上次遇到的相同模式。
因此,除了对 unique
的单个函数调用之外,我看不出你还能得到多少矢量化。无需使用 for
循环。
x = [1,1,1,1,2,2,2,3,3,4,4,4,4];
s = [1,2,3,4];
[valid, first] = max(bsxfun(@eq, x(:), s(:).'),[],1);
[~, last] = max(bsxfun(@eq, flipud(x(:)), s(:).'),[],1);
first(~valid) = 0;
last = numel(x)-last+1;
last(~valid) = 0;
这利用了这样一个事实,即 max
returns 的第二个输出是每个列中 第一个 最大化器的位置。此外,第一个输出用于确保每个值至少出现一次;如果不是这种情况,则结果将设置为零。因此,例如 s = [1,2,3,4,5]
的结果将是
first =
1 5 8 10 0
last =
4 7 9 13 0
要获得 last 个位置,使用相同的方法,只是使用翻转向量。
每个向量中的元素可以按任意顺序排列。