У меня есть два массива ячеек строк, и я хочу проверить, содержат ли они те же строки (они не должны быть в том же порядке, и при этом мы не знаем, имеют ли они те же длины).
Например:
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)
но затем мы не знаем заранее, что они имеют ту же длину (очевидный случай неравных). Таким образом, как Вы выполнили бы это сравнение самым эффективным способом, не пишущий слишком много случаев если/еще.
Вы можете использовать функцию 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 будет значительно медленнее.
Вы по-прежнему можете использовать функцию 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
Взгляните на функцию пересечь
Что говорит справка MATLAB:
[c, ia, ib] = пересечь (a, b)
также возвращает векторы индекса столбцаia
иib
такие, чтоc = a (ia)
иb (ib)
(илиc =
a (ia,:)
иb ( ib, :)).