2011-10-28 17 views
11

क्या "वेक्टर" संरचना का सरणी निर्दिष्ट करने का कोई तरीका है।संरचना का मैटलैब सरणी: फास्ट असाइनमेंट

वर्तमान में मैं

edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A. 
for i=1:1000000; edges(i).weight=1.0; end; 

लेकिन वह धीमी है, मैं की तरह

edges(:).weight=[rand(1000000,1)]; //with or without the square brackets. 

कोई भी विचार/सुझाव अधिक कुछ करने के लिए इस काम vectorize करने के लिए, इतना है कि यह तेजी से हो जाएगा चाहते हैं।

अग्रिम धन्यवाद।

+2

यह पोस्ट सहायता की हो सकती है: http://stackoverflow.com/questions/4166438/how-do-i-define-a-structure-in-matlab/4169216#4169216 – Amro

उत्तर

8

आप मैटलैब फ़ंक्शन deal का उपयोग करने का प्रयास कर सकते हैं, लेकिन मुझे लगता है कि इसे इनपुट को छोटा करने की आवश्यकता है (इस प्रश्न का उपयोग करके: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), हो सकता है कि कुछ आसान हो।

n=100000; 
edges(n)=struct('weight',1.0); 
m=mat2cell(rand(n,1),ones(n,1),1); 
[edges(:).weight]=deal(m{:}); 

इसके अलावा मैंने पाया कि यह लगभग जितनी जल्दी अपने कंप्यूटर पर पाश के लिए (~ पाश के लिए सौदा बनाम ~ 0.05s के लिए 0.35s) शायद mat2cell करने के लिए कॉल की वजह से नहीं है। यदि आप इसे एक से अधिक बार उपयोग करते हैं तो गति में अंतर कम हो जाता है लेकिन यह लूप के पक्ष में रहता है।

+0

बहुत बढ़िया धन्यवाद, धन्यवाद। – sumodds

+2

ये मेरे समय हैं। ऑक्टेव पर: इस विधि के लिए 100 किलोग्राम के लिए 177 और 1 मिलीलीटर के लिए 1.57s और यदि मैं लूप के लिए उपयोग करता हूं, तो यह 100 के लिए 230s की तरह होता है। MATLAB 200 बी (diff मशीन/ओएस): लूप के लिए उपरोक्त और .22s/2.2s का उपयोग कर 5s/49s। – sumodds

2

क्या आपको इस तरह से एक संरचना का विशेष रूप से उपयोग करने की आवश्यकता है?

स्ट्रक्चर के प्रत्येक सदस्य के लिए केवल एक अलग सरणी के साथ structs की अपनी सरणी को बदलने पर विचार करें।

weights = rand(1, 1000); 

आप एक struct सदस्य जो एक सरणी है है, तो आप एक अतिरिक्त आयाम बना सकते हैं:

matrices = rand(3, 3, 1000); 

आप सिर्फ बातें साफ रखना चाहते हैं, तो आप एक struct में इन सरणियों डाल सकता है:

edges.weights = weights; 
edges.matrices = matrices; 

लेकिन अगर आप structs की एक सरणी रखने की जरूरत है, मुझे लगता है कि आप कर सकते हैं

[edges.weight] = rand(1, 1000); 
+0

दोनों ही वही करते हैं। लेकिन, मुझे लगता है कि मुझे इसे structs (अर्थात् सरणी की वस्तुओं) की सरणी होने की आवश्यकता है और सरणी की संरचना नहीं है (एक बड़ी सरणी की एक बड़ी संरचना)। MATLAB में दोनों के बीच क्या अंतर है, क्या कोई है? मतलब स्मृति की w.r.t आवंटन और यदि हां, तो इसका निहितार्थ क्या है? – sumodds

+0

वैसे भी धन्यवाद। :) – sumodds

+1

अंतर यह है कि मैटलैब में, structs की एक सरणी ("संरचना-संगठित") पूरी तरह से अक्षम है क्योंकि प्रत्येक संरचना अपने प्रत्येक फ़ील्ड को एक अलग सरणी में संग्रहीत करती है, ताकि आप उन पर वेक्टरीकृत ऑपरेशन नहीं कर सकें। ब्रायन की इच्छा जैसे सरणी ("प्लानर-संगठित") की एक संरचना अपने प्रत्येक फ़ील्ड को आदिम सरणी में संग्रहीत करती है जो स्मृति में संगत होती है, और वेक्टरिज्ड (तेज़) मैटलैब फ़ंक्शन काम करेंगे। यह Matlab के लिए एक बेहतर संरचना है, और अधिक मूर्खतापूर्ण है। –

7

आप बस लिख सकते हैं:

edges = struct('weight', num2cell(rand(1000000,1))); 
13

यह सौदा या एक पाश (कम से कम अपने सिस्टम पर) की तुलना में बहुत तेजी से होता है:

N=10000; 
edge(N) = struct('weight',1.0); % initialize the array 
values = rand(1,N); % set the values as a vector 

W = mat2cell(values, 1,ones(1,N)); % convert values to a cell 
[edge(:).weight] = W{:}; 

सही पर घुंघराले ब्रेसिज़ का उपयोग करते हुए एक अल्पविराम से अलग कर देता है डब्ल्यू (यानी एन आउटपुट) में सभी मानों की मान सूची और दाईं ओर स्क्वायर ब्रेसेस का उपयोग करके उन एन आउटपुट को एन मानों को किनारे (:) वजन में असाइन किया जाता है।

+0

अच्छा! सिंथेटिक और व्यावहारिक रूप से सुरुचिपूर्ण! यह अच्छा होगा अगर Matlab वाक्यविन्यास ने एक तर्क अनुक्रम में सरणी को विस्तारित करने की अनुमति दी, जैसे '{value} {:}'।एक सेल वैल्यू सूची लेने के लिए एक फ़ंक्शन बनाने का प्रयास किया, लेकिन स्पष्ट रूप से यह 'varargout' को उसी तरह से असाइन करना पसंद नहीं करता है, जिस तरह से' सौदा() 'हाहा करता है। – eacousineau

+0

हूप्स, मैंने पाया कि मैं 'num2cell()' के बजाय 'mat2cell()' का उपयोग कर रहा था। यहां फ़ंक्शन है: ['cellexpand()'] (https://gist.github.com/eacousineau/9699289#file-cellexpand-m)। – eacousineau

+0

आप अज्ञात हैंडल का भी उपयोग कर सकते हैं: 'cellexpand = @ (x) x {:}; numexpand = @ (x) सेलेक्सपैंड (num2cell (x)); '। एक उदाहरण: '[ए, बी] = numexpand ([1, 2]);'। अधिक विशिष्ट उदाहरण: '[edge.weight] = numexpand ([edge.weight] + 50);' – eacousineau

1

कारण यह है कि आपके उदाहरण में structs ठीक से प्रारंभ नहीं होते हैं यह है कि आप जिस वाक्यविन्यास का उपयोग कर रहे हैं वह केवल स्ट्रक्चर सरणी में अंतिम तत्व को संबोधित करता है। एक nonxistent सरणी के लिए, उनमें से बाकी सूत्रों के साथ पूरी तरह से भर जाते हैं जिनके पास अपने सभी क्षेत्रों में डिफ़ॉल्ट मान [] है।

इस व्यवहार स्पष्ट करने के लिए, clear edges; edges(1:3) = struct('weight',1.0) के साथ एक लघु सरणी कर रहे हैं और edges(1), edges(2), और edges(3) में से प्रत्येक में देखने का प्रयास करें।edges(3) तत्व में आपके वजन में 1.0 है जैसा आप चाहते हैं; अन्य [] है।

स्ट्रक्चर की सरणी को कुशलतापूर्वक प्रारंभ करने के लिए वाक्यविन्यास इनमें से एक है।

% Using repmat and full assignment 
edges = repmat(struct('weight', 1.0), [1 1000]); 

% Using indexing 
% NOTE: Only correct if variable is uninitialized!!! 
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE 

नोट के बजाय सिर्फ 1000 जब अप्रारंभीकृत किनारों सरणी में सूचीबद्ध करने में 1:1000

edges(1:1000) फ़ॉर्म में कोई समस्या है: यदि edges पहले ही प्रारंभ हो चुका है, तो यह वाक्यविन्यास केवल चयनित तत्वों के मान अपडेट करेगा। यदि किनारों में 1000 से अधिक तत्व हैं, तो दूसरों को अपरिवर्तित छोड़ा जाएगा, और आपका कोड खराब हो जाएगा। या यदि edges एक अलग प्रकार है, तो आप अपने मौजूदा डेटाटाइप के आधार पर एक त्रुटि या अजीब व्यवहार प्राप्त कर सकते हैं। सुरक्षित होने के लिए, आपको इंडेक्सिंग सिंटैक्स का उपयोग शुरू करने से पहले clear edges करना होगा। इसलिए repmat फ़ॉर्म के साथ पूर्ण असाइनमेंट करना बेहतर है।

लेकिन: आप इसे कैसे प्रारंभ की परवाह किए बिना, एक इस तरह सरणी के- structs हमेशा पैदायशी बड़े डेटा सेट के लिए साथ काम करने के धीमी गति से होने जा रहा है। आप इस पर वास्तविक "वेक्टरकृत" संचालन नहीं कर सकते हैं क्योंकि आपके आदिम सरणी सभी को प्रत्येक संरचना तत्व के अंदर अलग mxArrays में विभाजित कर दिया जाता है। इसमें आपके प्रश्न में फ़ील्ड असाइनमेंट शामिल है - इसे सदिश बनाना संभव नहीं है। इसके बजाय, आपको ब्रायन एल के उत्तर जैसे स्ट्रक्चर-ऑफ-एरे स्विच करना चाहिए।

0

आप एक रिवर्स struct उपयोग कर सकते हैं और फिर इस

x.E(1)=1; 
x.E(2)=3; 
x.E(2)=8; 
x.E(3)=5; 

और फिर निम्न

x.E 

ans = 

    3  8  5 

तरह आपरेशन की तरह किसी भी त्रुटि बिना या इस

x.E(1:2)=2 

x = 

    E: [2 2 5] 
की तरह सभी कार्य कर

या शायद यह

x.E(1:3)=[2,3,4]*5 

x = 

    E: [10 15 20] 

यह for_loop से वास्तव में तेज़ है और आपको अपने प्रोग्राम को धीमा करने के लिए अन्य बड़े कार्यों की आवश्यकता नहीं है।

संबंधित मुद्दे