8

我有两个字符串元胞数组,我想检查它们是否包含相同的字符串(它们的顺序不必相同,我们也不知道它们是否具有相同的长度)。

例如:

a = {'2' '4' '1' '3'};
b = {'1' '2' '4' '3'};

或者

a = {'2' '4' '1' '3' '5'};
b = {'1' '2' '4' '3'};

首先我想到了,strcmp但这需要遍历一个单元格内容并与另一个单元格内容进行比较。我还考虑ismember过使用类似的东西:

ismember(a,b) & ismember(b,a)

但是我们事先并不知道它们的长度相同(显然是不相等的情况)。那么如何在不编写太多 if/else 案例的情况下以最有效的方式执行此比较。

4

3 回答 3

17

您可以使用函数SETXOR,它将返回不在两个元胞数组交集中的值。如果它返回一个空数组,则两个元胞数组包含相同的值:

arraysAreEqual = isempty(setxor(a,b));



编辑:一些性能指标......

由于您对性能测量感到好奇,我想我会根据Amro列出的两个解决方案(使用ISMEMBERSTRCMP / CELLFUN)来测试我的解决方案的速度。我首先创建了两个大型单元阵列:

a = cellstr(num2str((1:10000).'));  %'# A cell array with 10,000 strings
b = cellstr(num2str((1:10001).'));  %'# A cell array with 10,001 strings

接下来,我将每个解决方案运行 100 次以获得平均执行时间。然后,我交换ab重新运行它。结果如下:

    Method     |      Time     |  a and b swapped
---------------+---------------+------------------
Using SETXOR   |   0.0549 sec  |    0.0578 sec
Using ISMEMBER |   0.0856 sec  |    0.0426 sec
Using STRCMP   |       too long to bother ;)

请注意,SETXOR解决方案始终具有快速时序。如果a有不在b. _ 这是由于短路&&跳过了计算的后半部分(因为我们已经知道a并且b不包含相同的值)。但是,如果 中的所有值a也都在 中b,则ISMEMBER解决方案会明显变慢。

于 2010-07-12T19:42:30.970 回答
5

You can still use ISMEMBER function like you did with a small modification:

arraysAreEqual = all(ismember(a,b)) && all(ismember(b,a))

Also, you can write the loop version with STRCMP as one line:

arraysAreEqual = all( cellfun(@(s)any(strcmp(s,b)), a) )

EDIT: I'm adding a third solution adapted from another SO question:

g = grp2idx([a;b]);
v = all( unique(g(1:numel(a))) == unique(g(numel(a)+1:end)) );

In the same spirit, Im performed the time comparison (using the TIMEIT function):

function perfTests()
    a = cellstr( num2str((1:10000)') );            %#' fix SO highlighting
    b = a( randperm(length(a)) );

    timeit( @() func1(a,b) )
    timeit( @() func2(a,b) )
    timeit( @() func3(a,b) )
    timeit( @() func4(a,b) )
end

function v = func1(a,b)
    v = isempty(setxor(a,b));                      %# @gnovice answer
end

function v = func2(a,b)
    v = all(ismember(a,b)) && all(ismember(b,a));
end

function v = func3(a,b)
    v = all( cellfun(@(s)any(strcmp(s,b)), a) );
end

function v = func4(a,b)
    g = grp2idx([a;b]);
    v = all( unique(g(1:numel(a))) == unique(g(numel(a)+1:end)) );
end

and the results in the same order of functions (lower is better):

ans =
     0.032527
ans =
     0.055853
ans =
       8.6431
ans =
     0.022362
于 2010-07-12T20:06:09.977 回答
2

看看函数intersect

什么 MATLAB 帮助说:

[c, ia, ib] = intersect(a, b)还返回列索引向量iaib 这样的c = a(ia)b(ib)(或c = a(ia,:)b(ib,:)).

于 2010-07-12T19:33:28.277 回答