2012-02-15 42 views
18

Giả sử tôi có một mảng cấu trúc arr, trong đó mỗi phần tử có một loạt các trường, bao gồm một phần được gọi là val. Tôi muốn tăng lĩnh vực val mỗi phần tử của một số lượng không đổi, như vậy:Cập nhật một trường trong mỗi phần tử của mảng cấu trúc Matlab

for i = 1:length(arr) 
    arr(i).val = arr(i).val + 3; 
end 

Điều này rõ ràng làm việc, nhưng tôi cảm thấy cần phải có một cách để làm điều này chỉ trong một dòng mã (và không cho vòng lặp). Điều tốt nhất tôi đã đưa ra là hai dòng và yêu cầu biến tạm thời:

newVals = num2cell([arr.val] + 3); 
[arr.val] = deal(newVals{:}); 

Bất kỳ ý tưởng nào? Cảm ơn.

Trả lời

11

Chỉ cần một lưu ý, deal là không cần thiết có:

[arr.val] = newVals{:}; % achieves the same as deal(newVals{:}) 

Chỉ khác cách tôi biết làm thế nào để làm điều này (không có vòng lặp foor) đang sử dụng arrayfun để lặp qua mỗi struct trong mảng :

% make a struct array 
arr = [ struct('val',0,'id',1), struct('val',0,'id',2), struct('val',0,'id',3) ] 

% some attempts 
[arr.val]=arr.val; % fine 
[arr.val]=arr.val+3; % NOT fine :(

% works ! 
arr2 = arrayfun(@(s) setfield(s,'val',s.val+3),arr) 

Đó lệnh vòng cuối cùng trên mỗi struct trong arr và trả về một mới một nơi s.val đã được thiết lập để s.val=3.

Tôi nghĩ rằng điều này thực sự kém hiệu quả hơn so với hai lớp lót trước và vòng lặp for, vì nó trả về bản sao của arr thay vì hoạt động tại chỗ.

(Đó là một Matlab xấu hổ không hỗ trợ lập chỉ mục lớp như [arr.val]=num2cell([arr.val]+3){:}).

+0

Cảm ơn tip trên 'deal'. Tôi không biết về 'setfield', do đó, nó xuất hiện để làm điều đó trong một dòng, nhưng như bạn nói, điều này chắc chắn tồi tệ hơn so với giải pháp cho vòng lặp. Đối với việc lập chỉ mục như thế, tôi đã xem xét nó một lúc trước; về cơ bản, Mathworks tuyên bố rằng việc hỗ trợ mọi thứ như thế sẽ buộc các thay đổi phá vỡ tính tương thích với trình phân tích cú pháp. Đó là một sự xấu hổ, vì nó lỗi cho tôi hầu như mỗi khi tôi viết bất kỳ mã Matlab nào. – Carl

+0

Cảm ơn câu trả lời này! Trong MATLAB 2013b, [arr.val] = newVals {:} hoạt động BUT arr.val = newVals {:}. Chính xác những gì các dấu ngoặc làm trong trường hợp này? –

+0

'arrayfun' chỉ là một trình bao bọc cho vòng lặp' for' trong MATLAB, vì vậy về mặt kỹ thuật bạn vẫn đang sử dụng vòng lặp, mặc dù trong ngụy trang. – Adriaan

1

Có phải tất cả các trường trong cấu trúc vô hướng đó hoặc có cùng kích thước không? Nếu vậy, cách Matlab thành ngữ để làm điều này là sắp xếp lại cấu trúc của bạn thành một cấu trúc vô hướng với các mảng trong mỗi trường của nó, thay vì một mảng các cấu trúc với các giá trị vô hướng trong các trường. Sau đó, bạn có thể thực hiện các hoạt động được vector hóa trên các trường, như arr.val = arr.val + 3;. Xem liệu bạn có thể sắp xếp lại dữ liệu của mình hay không. Làm theo cách này hiệu quả hơn nhiều trong cả thời gian lẫn trí nhớ; đó có thể là lý do tại sao Matlab không cung cấp cú pháp thuận tiện cho việc vận hành trên các trường của mảng các cấu trúc.

0

nếu mảng struct bạn đang cố gắng để thiết lập là một tập các đối tượng đồ họa (dòng xử lý, xử lý hình, rìu tay cầm, vv), thì bạn cần phải sử dụng chức năng set:

x = (1:10)'; 
Y = rand(10,5); 
l = plot(x,Y,'-k'); % returns an array of line handles in l 
set(l,'Color','r'); % sets the property 'Color' for all the five lines in l 
Các vấn đề liên quan