2010-07-12 44 views
8

Tôi có hai mảng ô của chuỗi và tôi muốn kiểm tra xem chúng có chứa các chuỗi giống nhau hay không (chúng không nhất thiết phải theo cùng một thứ tự, cũng như chúng ta không biết chúng có cùng độ dài).MATLAB: so sánh mảng ô của chuỗi

Ví dụ:

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

hoặc

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

Trước tiên tôi nghĩ đến strcmp nhưng nó sẽ đòi hỏi lặp trên một nội dung di động và so sánh với người kia. Tôi cũng coi ismember bằng cách sử dụng một cái gì đó như:

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

nhưng sau đó chúng ta không biết trước rằng họ có cùng độ dài (trường hợp rõ ràng của bất bình đẳng). Vì vậy, làm thế nào bạn sẽ thực hiện so sánh này một cách hiệu quả nhất mà không cần viết quá nhiều trường hợp nếu/else.

Trả lời

17

Bạn có thể sử dụng hàm SETXOR, sẽ trả về các giá trị không nằm trong giao điểm của hai mảng ô. Nếu nó trả về một mảng trống rỗng, sau đó hai mảng tế bào chứa các giá trị như nhau:

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



EDIT: Một số biện pháp thực hiện ...

Vì bạn đã tò mò về các biện pháp hiệu suất, tôi nghĩ tôi muốn kiểm tra tốc độ của giải pháp của tôi so với hai giải pháp được liệt kê bởi Amro (sử dụng ISMEMBERSTRCMP/CELLFUN). Lần đầu tiên tôi tạo hai mảng ô lớn:

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

Tiếp theo, tôi chạy từng giải pháp 100 lần để có thời gian thực hiện trung bình. Sau đó, tôi đổi chỗ ab rồi chạy lại. Dưới đây là kết quả:

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 ;) 

Lưu ý rằng giải pháp SETXOR có thời gian nhanh nhất quán. Giải pháp ISMEMBER sẽ thực sự chạy nhanh hơn một chút nếu a có các phần tử không nằm trong b. Điều này là do short-circuit && bỏ qua nửa sau của phép tính (vì chúng tôi đã biết ab không chứa các giá trị giống nhau). Tuy nhiên, nếu tất cả các giá trị trong a cũng có trong b, giải pháp ISMEMBER chậm hơn đáng kể.

+1

Để đánh giá hiệu suất, bạn sẽ cần một giải pháp khác để so sánh, như đề xuất bạn đã thực hiện bằng vòng lặp và [STRCMP] (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/strcmp. html). Tôi tưởng tượng hiệu suất sẽ hoàn toàn tốt đẹp, nhưng nếu bạn phát hiện ra rằng việc sử dụng [SETXOR] (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/setxor.html) thực sự kết thúc là một nút cổ chai trong quá trình xử lý của bạn, bạn có thể thử xem mã nguồn của nó ('type setxor' hoặc' edit setxor') và viết lại nó bằng cách cắt bớt một số kiểm tra lỗi, v.v. – gnovice

+1

cảm ơn, tôi nghĩ rằng tôi thấy những gì @Mikhail đang cố gắng làm. Điều gì về hiệu suất? có vẻ như XOR của hai bộ là một hoạt động tốn kém khi tất cả tôi cần là một loại câu trả lời đúng/sai – Dave

+0

oops, tôi đã chỉnh sửa nhận xét của mình và làm rối trật tự .. xin lỗi – Dave

2

Hãy nhìn vào các chức năng intersect

gì MATLAB Help nói: vectơ

[c, ia, ib] = intersect(a, b) cũng lợi nhuận chỉ số cột iaibc = a(ia)b(ib) (hoặc c = a(ia,:)b(ib,:)).

+0

Tôi không chắc chắn làm thế nào để có được các giải pháp từ kết quả của 'intersect' – Dave

+0

Nó phụ thuộc vào những gì bạn chính xác phải làm. Nếu bạn cần một boolean vô hướng mà cả hai vectơ chứa cùng một chuỗi thì giải pháp của gnovice là câu trả lời đúng cho bạn. – Mikhail

5

Bạn vẫn có thể sử dụng ISMEMBER chức năng giống như bạn đã làm với một thay đổi nhỏ:

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

Ngoài ra, bạn có thể viết các phiên bản lặp với strcmp như một dòng:

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

EDIT: Tôi đang thêm giải pháp thứ ba được điều chỉnh từ một số khác SO question:

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

Trong tinh thần đó, Im thực hiện việc so sánh thời gian (sử dụng TIMEIT chức năng):

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 

và kết quả theo thứ tự của các chức năng (thấp hơn là tốt hơn):

ans = 
    0.032527 
ans = 
    0.055853 
ans = 
     8.6431 
ans = 
    0.022362