2014-09-04 3 views
2

У меня есть 2 ячейки строк, и я хотел бы заказать их в соответствии с первым.Matlab, упорядочить ячейки строк в соответствии с первым

A = {'a';'b';'c'} 
B = {'b';'a';'c'} 

idx = [2,1,3] % TO FIND 

B=B(idx); 

Я хотел бы найти способ, чтобы найти idx ...

+0

Смотри также [Сопоставление идентификаторов двух векторов] (http://stackoverflow.com/questions/21788606/mapping-ids-of-two-vectors/21790654#21790654) –

ответ

2

Это кажется значительно быстрее, чем использование ismember (хотя, по общему признанию, менее ясное, чем @rayryeng's answer). С благодарностью @ Дивакар за исправление этого ответа.

[~, indA] = sort(A); 
[~, indB] = sort(B); 
idx = indA(indB); 
+0

OH. Хорошее использование 'sort'. У меня было чувство, что я использую 'sort', но я не мог точно определить, как использовать другой массив' B'. Красиво сделано +1. – rayryeng

+0

@rayryeng Спасибо! На самом деле запутать игру с вложенными сортировками. Иногда я просто пытаюсь сочетать (их не так много), пока не найду то, что работает :-) (BTW уже +1 тоже) –

+0

Что делать, если некоторые элементы не являются общими между A и B или если есть повторение элементов внутри каждого из эти ячейки массивов? Возможно, что-то вроде этого: 'A = {'a'; 'b'; 'c'; 'd'}, B = {'b'; 'a'; 'c'; 'a'}'. – Divakar

3

Используйте второй выход ismember. ismember указывает, находятся ли значения в первом наборе в любом месте во втором наборе. Второй вывод указывает, где находятся эти значения, если мы найдем что-нибудь. Таким образом:

A = {'a';'b';'c'} 
B = {'b';'a';'c'} 
[~,idx] = ismember(A, B); 

Обратите внимание, что при объявлении массивов ячеек имеется небольшая опечатка. У вас есть толстая кишка между b и c для A и a и c для B. Я поместил туда двоеточие для обоих.

Таким образом, мы получаем:

idx = 

    2 
    1 
    3 

Бенчмаркинг

У нас есть три очень хорошие алгоритмы здесь. Таким образом, давайте посмотрим, как это происходит, выполняя тест бенчмаркинга. Я собираюсь создать массив случайных символов размером 10000 х 1 строчных букв. Затем он будет инкапсулирован в массив ячеек 10000 x 1, где каждая ячейка представляет собой единый массив символов. Я построю A таким образом, а B представляет собой случайную перестановку элементов в A. Это код, который я написал, чтобы сделать это для нас:

letters = char(97 + (0:25)); 
rng(123); %// Set seed for reproducibility 
ind = randi(26, [10000, 1]); 
lettersMat = letters(ind); 
A = mat2cell(lettersMat, ones(10000,1), 1); 
B = A(randperm(10000)); 

Теперь ... вот приходит код тестирования:

clear all; 
close all; 

letters = char(97 + (0:25)); 
rng(123); %// Set seed for reproducibility 
ind = randi(26, [10000, 1]); 
lettersMat = letters(ind); 
A = mat2cell(lettersMat, 1, ones(10000,1)); 
B = A(randperm(10000)); 

tic; 
[~,idx] = ismember(A,B); 
t = toc; 

fprintf('ismember: %f\n', t); 

clear idx; %// Make sure test is unbiased 

tic; 
[~,idx] = max(bsxfun(@eq,char(A),char(B)')); 
t = toc; 

fprintf('bsxfun: %f\n', t); 

clear idx; %// Make sure test is unbiased 

tic; 
[~, indA] = sort(A); 
[~, indB] = sort(B); 
idx = indB(indA); 
t = toc; 

fprintf('sort: %f\n', t); 

Это то, что я получаю для синхронизации:

ismember: 0.058947 
bsxfun: 0.110809 
sort: 0.006054 

Подход Луиса Мендо самый быстрый, затем ismember, а затем, наконец, bsxfun. Для компактности кода предпочтительнее ismember, но для производительности лучше sort. Лично я считаю, что bsxfun должен побеждать, потому что это такая хорошая функция для использования;).

+0

Th у меня был просто ленивый комментарий от меня !;) +1. – Divakar

+0

@ Divakar - ahaha thanks :) Я буквально собирался нажать кнопку сообщения, когда увидел ваш комментарий. Я бы не опубликовал, если бы увидел ваш комментарий раньше. – rayryeng

+0

Я рад, что вы выложили действительно! И всегда здорово, что есть объяснения. – Divakar

2

Я должен был прыгать, как это кажется производительность выполнения может быть критерий здесь :)

Предполагая, что вы имеете дело со скалярными строк (один символ в каждой клетке), вот мое взятие, что работает даже если у вас есть не-commmon элементы между A и B и использует очень мощный bsxfun и как таковой я действительно надеюсь, что это будет во время выполнения эффективных -

[v,idx] = max(bsxfun(@eq,char(A),char(B)')); 
idx = v.*idx 

Пример -

A = 
    'a' 'b' 'c' 'd' 
B = 
    'b' 'a' 'c' 'e' 
idx = 
    2  1  3  0 

Для конкретного случая, когда у вас нет не-общих элементов между A и B, он становится один вкладыш -

[~,idx] = max(bsxfun(@eq,char(A),char(B)')) 

Пример -

A = 
    'a' 'b' 'c' 
B = 
    'b' 'a' 'c' 
idx = 
    2  1  3 
+0

Ахахахаха, я сказал себе, что Дивакар, скорее всего, придет с решением 'bsxfun'. Я не думал, что на самом деле я прав. +1. – rayryeng

+0

hahaha, тогда я буду тестировать :). Дайте мне минуту. – rayryeng

+0

Я действительно собирался создать кучу случайных уникальных персонажей! – rayryeng

Смежные вопросы