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)

но тогда мы не знаем в заранее, что они имеют одинаковую длину (очевидный случай неравных). Итак, как бы вы выполнили это сравнение наиболее эффективным способом, не записывая слишком много случаев if/else.

3 ответов


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

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



EDIT: некоторые показатели эффективности...

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


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

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

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

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

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

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

в том же духе Im выполнил сравнение времени (используя TIMEIT


взгляните на функцию intersect

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

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