2015-08-21 15 views
6

Mam dwa wektory a i b jako przykład:Tworzenie ciągów z indeksów dwóch wektorów w Matlab

a = [1 2 3 4]; b = [5 6 7 8];

Chcę utworzyć ciągi z indeksów a i b:

c1 = a(1):b(1) = [1 2 3 4 5]; 
c2 = a(2):b(2) = [2 3 4 5 6]; 
c3 = a(3):b(3) = [3 4 5 6 7]; 
c4 = a(4):b(4) = [4 5 6 7 8]; 

Następnie chcę połączyć otrzymane ciągi:

C = cat(2, c1, c2, c3, c4) = [1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8];

Chciałbym ogólne rozwiązanie, które pomoże mi zautomatyzować ten algorytm.

+0

nie 'a (2) B (2) = [3 4 5 6 ] '? Czy naprawdę chcesz również ciągi, a nie tylko wektory dubletów? – Dan

+0

Tak, masz rację, dokonałem edycji. Z początku coś zmieniłem i zapomniałem zaktualizować wynik. – Bowecho

Odpowiedz

5

Rozwiązanie

To powinno załatwić sprawę bez użycia pętli:

>> a = [1 3 4 5]; 
>> b = [5 6 7 8]; 
>> resultstr = num2str(cell2mat(arrayfun(@(x,y) x:y,a,b,'UniformOutput',false))) 

resultstr = 

1 2 3 4 5 3 4 5 6 4 5 6 7 5 6 7 8 

wydajność

Próbowałem zrobić szybkie porównanie tej metody, Luis Mendo's method i pętlę for (patrz np. A. Visser's answer). Stworzyłem dwie tablice z liczbami pseudolosowymi od 1 do 50 i od 501 do 1000, a także obliczono czasy obliczeń dla rozmiarów tablic od 1 do 300, pomijając konwersję ciągów. anwer

Performance comparison

Luis Mendo jest wyraźnym zwycięzcą, jeśli chodzi o czas złożoności arrayfun wydaje się być na równi z bsxfun. Pętla for jest znacznie gorsza, z wyjątkiem bardzo małych rozmiarów tablic, ale nie jestem pewien, czy można tam zaufać.

Kod można znaleźć here. Byłbym bardzo szczęśliwy, gdyby otrzymałem informację zwrotną. Nie jestem pewien co do tych pomiarów.

+0

Dzięki, szukałem takiego podejścia. – Bowecho

+0

Tak, więc wiesz, 'arrayfun' jest w rzeczywistości przebraną pętlą, mimo że pasuje do jednej linii, ale ładnie zrobione tak! –

+0

Benoit_11: Różnica w wydajności jest jednak dość drastyczna, pętla 'for' jest ~ 20-30 razy wolniejsza na moim komputerze, prawdopodobnie dlatego, że wynikowa tablica nie może być wcześniej przydzielona - nie jestem jednak ekspertem od wydajności MATLAB ... – dasdingonesin

1

Spróbuj czegoś takiego:

A = [1:5; 5:8];, C = []; 
for i = A, C = [C i(1):i(2)]; end 
Cstr = num2str(C); 
1

chciałbym to zrobić:

a = [1 3 4 5]; b = [5 6 7 8]; 
c =[]; 
for i =1:length(a) 
    c = [c [a(i):b(i)]]; 
end 
num2str(c) 
1

Przede wszystkim, nie należy przypisywać zmienne jak C1, C2, C3 itp zastosowania komórek za to.

Używałbym do tego celu Pętli for, chociaż prawdopodobnie istnieje lepsza alternatywa.

a = [1 3 4 5]; b = [5 6 7 8]; 
C = []; 
for ii = 1:length(a) 
    tmp = a(ii):b(ii); 
    C = [C tmp]; 
end 

ten sposób tmp przechowuje twoje oddzielne tablice, a następnie dodaje się wiersz dodaje go do wcześniej istniejącej tablicy C.

5

Można tego dokonać bez pętli (czy to for, arrayfun lub cellfun) przy użyciu bsxfun's masking capability.Działa to również wtedy, gdy "łańcuchy" mają różne długości, jak w poniższym przykładzie.

a = [1 2 3]; 
b = [3 5 6]; 
m = (0:max(b-a)).'; %' 
C = bsxfun(@plus, a, m); 
mask = bsxfun(@le, m, b-a); 
C = C(mask).'; 

Rezultat w tym przypadku jest:

C = 
    1  2  3  2  3  4  5  3  4  5  6 
+0

Dziękuję, @Luis Mendo, ładnie wykonane. – Bowecho

1

Dla zabawy:

a = [1 2 3 4]; b = [5 6 7 8]; 

A=fliplr(gallery('circul',fliplr([a,b]))); 
B=A(1:numel(a)+1,1:numel(a)); 
C=num2str(B(:).') 
Powiązane problemy