2013-01-15 34 views
15

Tôi có hai vectơ, idx1idx2 và tôi muốn lấy các giá trị giữa chúng. Nếu idx1idx2 là con số và không vectơ, tôi có thể làm điều đó theo cách sau:Vector hóa Notion of Colon (:) - giá trị giữa hai vectơ trong MATLAB

idx1=1; 
idx2=5; 
values=idx1:idx2 

% Result 
% values = 
% 
% 1  2  3  4  5 

Nhưng trong trường hợp của tôi, idx1idx2 là vectơ có độ dài khác nhau. Ví dụ, đối với chiều dài = 2:

idx1=[5,9]; 
idx2=[9 11]; 

Tôi có thể sử dụng toán tử ruột kết trực tiếp có được các giá trị ở giữa? Đây là, một cái gì đó tương tự như sau:

values = [5  6  7  8  9  9 10 11] 

Tôi biết tôi có thể làm idx1(1):idx2(1)idx1(2):idx2(2), điều này được, trích xuất các giá trị cho mỗi cột riêng biệt, vì vậy nếu không có giải pháp khác, tôi có thể làm điều này với một cho vòng lặp, nhưng có lẽ Matlab có thể làm điều này dễ dàng hơn.

+0

'giá trị' không thể có trong MATLAB. Một 5-vector theo chiều dọc concatentated bởi một 3-vector? – petrichor

+0

Có, bạn đúng, xin lỗi. Tôi sẽ sửa nó. Tôi không quan tâm nếu các giá trị là tất cả trong cùng một hàng, tôi chỉ cần tất cả các giá trị giữa các chỉ mục đó. – Digna

+0

Có một bài đăng trên blog tuyệt vời về chủ đề này của Loren tại Mathworks: [Vector hóa Notion of Colon (:)] (http://blogs.mathworks.com/loren/2008/10/13/vectorizing-the-notion- of-colon) – knedlsepp

Trả lời

11

Kết quả mẫu của bạn không hợp pháp. Ma trận không thể có các hàng có độ dài khác nhau. Những gì bạn có thể làm là tạo ra một mảng tế bào sử dụng arrayfun:

values = arrayfun(@colon, idx1, idx2, 'Uniform', false) 

Để chuyển đổi các mảng tế bào kết quả vào một vector, bạn có thể sử dụng cell2mat:

values = cell2mat(values); 

Ngoài ra, nếu tất cả các vector trong tế bào dẫn đến mảng có cùng độ dài, bạn có thể xây dựng một ma trận đầu ra như sau:

values = vertcat(values{:}); 
+1

Cảm ơn, điều đó giúp ích. Như tôi chỉ cần các giá trị và tôi không nhớ từ hàng mà tôi đã thu được chúng, tôi có thể sử dụng 'horzcat' và' unique', như sau: 'values ​​= unique (horzcat (values ​​{:}));' I sẽ đọc thêm về arrayfun, nó có vẻ rất hữu ích – Digna

+2

@Digna Nó có thể trông khá, nhưng đừng lạm dụng nó. Nó khá chậm khi so sánh với vòng lặp 'for' (thậm chí nhiều hơn nếu một giải pháp" vectơ hóa "tồn tại), vì vậy bạn thường thích giải pháp thứ hai (trừ khi tốc độ không phải là vấn đề) ... Cũng lưu ý rằng bạn có thể viết' [blah blah] 'thay vì' horzcat (blah blah) '. –

0

Hãy thử lấy sự kết hợp của bộ này. Căn cứ vào giá trị của idx1idx2 bạn cung cấp, chạy

values = union(idx1(1):idx1(2), idx2(1):idx2(2)); 

nào sẽ mang lại một vector với các giá trị [5 6 7 8 9 10 11], như mong muốn.

+0

Cảm ơn bạn đã trả lời. Vấn đề là 'idx1' và' idx2' có thể có bất kỳ độ dài nào (nó phụ thuộc vào tín hiệu tôi đang xử lý), và giải pháp này sẽ khó áp dụng trong trường hợp này, phải không? (Có lẽ tôi đang thiếu một cái gì đó) :) – Digna

+0

Ah, rất tiếc. Xin lỗi, tôi hiểu nhầm câu hỏi. Lấy sản phẩm Descartes bằng cách sử dụng 'arrayfun' dường như là cách để đi đến đây. – benjwadams

0

Tôi không thể nhận được giải pháp @ Eitan để hoạt động, dường như bạn cần chỉ định tham số cho dấu hai chấm. Việc sửa đổi nhỏ mà sau nhận nó làm việc trên phiên bản R2010b tôi:

step = 1; 
idx1 = [5, 9]; 
idx2 = [9, 11]; 
values = arrayfun(@(x,y)colon(x, step, y), idx1, idx2, 'UniformOutput', false); 
values=vertcat(cell2mat(values)); 

Lưu ý rằng step = 1 thực sự là giá trị mặc định trong colon, và Uniform có thể được sử dụng thay cho UniformOutput, nhưng tôi đã bao gồm những vì lợi ích đầy đủ.

0

Có một bài đăng trên blog tuyệt vời theo số Loren được gọi là Vectorizing the Notion of Colon (:). Nó bao gồm một câu trả lời đó là khoảng 5 lần nhanh hơn (đối với mảng lớn) so với sử dụng arrayfun hoặc một for -loop và cũng tương tự như chạy dài-giải mã:

Ý tưởng là để mở rộng thư đại tràng trình tự ra. Tôi biết độ dài của mỗi chuỗi vì vậy tôi biết các điểm bắt đầu trong mảng đầu ra. Điền các giá trị sau giá trị bắt đầu bằng 1 giây. Sau đó, tôi tìm ra số lượng để nhảy từ cuối một chuỗi đến đầu của chuỗi tiếp theo. Nếu có giá trị bắt đầu lặp lại, số lần nhảy có thể âm.Sau khi mảng này được lấp đầy, đầu ra chỉ đơn giản là tổng tích lũy hoặc cumsum của chuỗi.

function x = coloncatrld(start, stop) 
% COLONCAT Concatenate colon expressions 
% X = COLONCAT(START,STOP) returns a vector containing the values 
% [START(1):STOP(1) START(2):STOP(2) START(END):STOP(END)]. 

% Based on Peter Acklam's code for run length decoding. 
len = stop - start + 1; 

% keep only sequences whose length is positive 
pos = len > 0; 
start = start(pos); 
stop = stop(pos); 
len = len(pos); 
if isempty(len) 
    x = []; 
    return; 
end 

% expand out the colon expressions 
endlocs = cumsum(len); 
incr = ones(1, endlocs(end)); 
jumps = start(2:end) - stop(1:end-1); 
incr(endlocs(1:end-1)+1) = jumps; 
incr(1) = start(1); 
x = cumsum(incr); 
Các vấn đề liên quan