MATLAB: сравнение массивов ячеек строки

У меня есть два массива ячеек строк, и я хочу проверить, содержат ли они те же строки (они не должны быть в том же порядке, и при этом мы не знаем, имеют ли они те же длины).

Например:

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)

но затем мы не знаем заранее, что они имеют ту же длину (очевидный случай неравных). Таким образом, как Вы выполнили бы это сравнение самым эффективным способом, не пишущий слишком много случаев если/еще.

8
задан Dave 12 July 2010 в 19:28
поделиться

3 ответа

Вы можете использовать функцию SETXOR , которая вернет значения, которые не находятся на пересечении двух массивов ячеек. Если он возвращает пустой массив, то два массива ячеек содержат одинаковые значения:

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



РЕДАКТИРОВАТЬ: Некоторые показатели производительности ...

Поскольку вам было интересно узнать о показателях производительности, я решил проверить скорость своего решения против двух решений, перечисленных Амро (которые используют ISMEMBER и STRCMP / 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 раз, чтобы получить среднее время выполнения. Затем я поменял местами a и b и перезапустил его. Вот результаты:

    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 имеет стабильно быструю синхронизацию. Решение ISMEMBER будет работать немного быстрее, если a содержит элементы, которых нет в b . Это происходит из-за короткого замыкания && , которое пропускает вторую половину расчета (поскольку мы уже знаем, что a и b не содержат те же значения). Однако, если все значения в a также находятся в b , решение ISMEMBER будет значительно медленнее.

17
ответ дан 5 December 2019 в 06:52
поделиться

Вы по-прежнему можете использовать функцию ISMEMBER, как и с небольшой модификацией:

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

Кроме того, вы можете записать версию цикла с помощью STRCMP в виде одной строки:

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

EDIT: Я добавляю третье адаптированное решение из другого вопроса SO :

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

В том же духе Im выполнил сравнение времени (используя функцию TIMEIT ):

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

и результаты в том же порядке функций ( чем ниже, тем лучше):

ans =
     0.032527
ans =
     0.055853
ans =
       8.6431
ans =
     0.022362
5
ответ дан 5 December 2019 в 06:52
поделиться

Взгляните на функцию пересечь

Что говорит справка MATLAB:

[c, ia, ib] = пересечь (a, b) также возвращает векторы индекса столбца ia и ib такие, что c = a (ia) и b (ib) (или c = a (ia,:) и b ( ib, :)).

2
ответ дан 5 December 2019 в 06:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: