没有重复的行 - MATLAB
Rows without repetitions - MATLAB
我有一个 matrix
(4096x4) 包含从 8 个数字池中取出的四个值的所有可能组合。
...
3 63 39 3
3 63 39 19
3 63 39 23
3 63 39 39
...
我只对包含四个唯一值的矩阵行感兴趣。例如,在上面的部分中,第一行和最后一行应该被删除,给我们 -
...
3 63 39 19
3 63 39 23
...
我当前的解决方案感觉不够优雅——基本上,我遍历每一行并将其添加到 result
矩阵(如果它包含四个唯一值):
result = [];
for row = 1:size(matrix,1)
if length(unique(matrix(row,:)))==4
result = cat(1,result,matrix(row,:));
end
end
有没有更好的方法?
方法 #1
基于
sortedmatrix = sort(matrix,2)
result = matrix(all(diff(sortedmatrix,[],2)~=0,2),:)
将其分解为几个步骤进行解释
- 按列排序,使每行中的重复值彼此相邻。我们用
sort
来完成这个任务。
- 查找连续元素之间的差异,这将在排序后捕获那些重复的元素。
diff
是用于此目的的工具。
- 对于带有
at least one zero
的任何行表示具有重复行的行。换句话说,任何带有 no zero
的行都表示没有重复行,我们希望在输出中包含这些行。 all
我们在这里完成了工作,以获得此类匹配项的逻辑数组。
- 最后,我们使用
matrix indexing
到 select 来自 matrix
的那些行以获得预期的输出。
方法 #2
这可能是一种基于实验性 bsxfun
的方法,因为它不会节省内存 -
matches = bsxfun(@eq,matrix,permute(matrix,[1 3 2]))
result = matrix(all(all(sum(matches,2)==1,2),3),:)
将其分解为几个步骤进行解释
- 在
bsxfun
. 的同一行中找到每个元素与所有其他元素匹配的逻辑数组
- 通过将
dim-2
个匹配项中的匹配项相加,然后在 dim-2
和 dim-3
中找到 all ones
个元素来寻找“非口是心非”,从而获得相同的索引数组与我们之前基于 diff + sort
的方法一样。
- 使用二进制索引数组 select 来自
matrix
的适当行作为最终输出。
方法 #3
从 MATLAB File-exchange 的 post combinator
获得帮助
并假设您在名为 pool8
的数组中有 8
值池,您可以像这样直接获得 result
-
result = pool8(combinator(8,4,'p'))
combinator(8,4,'p')
基本上让我们立即获得 8
元素的索引 4
并且没有重复。我们使用这些索引索引到 pool
并获得预期的输出。
对于有限数量的池,这将起作用。创建一个唯一数组,遍历池中的每个数字,计算它在行中出现的次数,如果找到一个或零个数字,则只将 IsUnique
保持为 1。接下来,找到 IsUnique
仍然是 1 的位置,提取这些行,我们就完成了。
matrix = [3,63,39,3;3,63,39,19;3,63,39,23;3,63,39,39;3,63,39,39;3,63,39,39];
IsUnique = ones(size(matrix,1),1);
pool = [3,63,39,19,23,6,7,8];
for NumberInPool = 1:8
Temp = sum((matrix == pool(NumberInPool))')';
IsUnique = IsUnique .* (Temp<2);
end
UniquePositions = find(IsUnique==1);
result = matrix(UniquePositions,:)
我有一个 matrix
(4096x4) 包含从 8 个数字池中取出的四个值的所有可能组合。
...
3 63 39 3
3 63 39 19
3 63 39 23
3 63 39 39
...
我只对包含四个唯一值的矩阵行感兴趣。例如,在上面的部分中,第一行和最后一行应该被删除,给我们 -
...
3 63 39 19
3 63 39 23
...
我当前的解决方案感觉不够优雅——基本上,我遍历每一行并将其添加到 result
矩阵(如果它包含四个唯一值):
result = [];
for row = 1:size(matrix,1)
if length(unique(matrix(row,:)))==4
result = cat(1,result,matrix(row,:));
end
end
有没有更好的方法?
方法 #1
基于sortedmatrix = sort(matrix,2)
result = matrix(all(diff(sortedmatrix,[],2)~=0,2),:)
将其分解为几个步骤进行解释
- 按列排序,使每行中的重复值彼此相邻。我们用
sort
来完成这个任务。 - 查找连续元素之间的差异,这将在排序后捕获那些重复的元素。
diff
是用于此目的的工具。 - 对于带有
at least one zero
的任何行表示具有重复行的行。换句话说,任何带有no zero
的行都表示没有重复行,我们希望在输出中包含这些行。all
我们在这里完成了工作,以获得此类匹配项的逻辑数组。 - 最后,我们使用
matrix indexing
到 select 来自matrix
的那些行以获得预期的输出。
方法 #2
这可能是一种基于实验性 bsxfun
的方法,因为它不会节省内存 -
matches = bsxfun(@eq,matrix,permute(matrix,[1 3 2]))
result = matrix(all(all(sum(matches,2)==1,2),3),:)
将其分解为几个步骤进行解释
- 在
bsxfun
. 的同一行中找到每个元素与所有其他元素匹配的逻辑数组
- 通过将
dim-2
个匹配项中的匹配项相加,然后在dim-2
和dim-3
中找到all ones
个元素来寻找“非口是心非”,从而获得相同的索引数组与我们之前基于diff + sort
的方法一样。 - 使用二进制索引数组 select 来自
matrix
的适当行作为最终输出。
方法 #3
从 MATLAB File-exchange 的 post combinator
获得帮助
并假设您在名为 pool8
的数组中有 8
值池,您可以像这样直接获得 result
-
result = pool8(combinator(8,4,'p'))
combinator(8,4,'p')
基本上让我们立即获得 8
元素的索引 4
并且没有重复。我们使用这些索引索引到 pool
并获得预期的输出。
对于有限数量的池,这将起作用。创建一个唯一数组,遍历池中的每个数字,计算它在行中出现的次数,如果找到一个或零个数字,则只将 IsUnique
保持为 1。接下来,找到 IsUnique
仍然是 1 的位置,提取这些行,我们就完成了。
matrix = [3,63,39,3;3,63,39,19;3,63,39,23;3,63,39,39;3,63,39,39;3,63,39,39];
IsUnique = ones(size(matrix,1),1);
pool = [3,63,39,19,23,6,7,8];
for NumberInPool = 1:8
Temp = sum((matrix == pool(NumberInPool))')';
IsUnique = IsUnique .* (Temp<2);
end
UniquePositions = find(IsUnique==1);
result = matrix(UniquePositions,:)