Вопрос:

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

matlab string comparison vectorization cell-array

26864 просмотра

3 ответа

364 Репутация автора

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

Например:

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.

Автор: Dave Источник Размещён: 12.07.2010 07:28

Ответы (3)


2 плюса

4895 Репутация автора

Посмотрите на функцию intersect

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

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

Автор: Mikhail Размещён: 12.07.2010 07:33

17 плюса

120351 Репутация автора

Решение

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

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



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

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

Автор: gnovice Размещён: 12.07.2010 07:42

5 плюса

117567 Репутация автора

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

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

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

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

РЕДАКТИРОВАТЬ: я добавляю третье решение, адаптированное из другого вопроса 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
Автор: Amro Размещён: 12.07.2010 08:06
Вопросы из категории :
32x32