2009-04-17 19 views
67

मुझे एक समस्या है। मुझे MATLAB में एक एन-आयामी मैट्रिक्स में प्रत्येक तत्व के माध्यम से पुनरावृत्त करने की आवश्यकता है। समस्या यह है कि, मुझे नहीं पता कि यह मनमानी संख्याओं के लिए कैसे किया जाए। मुझे पता है कि मैं कह सकता हूंMATLAB में एन-आयामी मैट्रिक्स में प्रत्येक तत्व के माध्यम से मैं फिर से कैसे सक्रिय करूं?

for i = 1:size(m,1) 
    for j = 1:size(m,2) 
     for k = 1:size(m,3) 

और इसी तरह, लेकिन क्या मनमानी संख्याओं के लिए इसे करने का कोई तरीका है?

+12

मैटलैब शब्दावली नोट: मैटलैब में कोर डेटा प्रकारों की एक छोटी संख्या है। सबसे महत्वपूर्ण हैं: संरचना, मैट्रिक्स, और सेल सरणी। एक मैट्रिक्स के हिस्सों का जिक्र करते समय, "तत्व" शब्द का उपयोग करना आम है, और सेल सेल के हिस्सों को संदर्भित करने के लिए "सेल" शब्द आरक्षित करना है। सेल सरणी और मैट्रिस में कई वाक्य रचनात्मक और अर्थपूर्ण अंतर होते हैं, भले ही दोनों एन-आयामी डेटा संरचनाएं हों। –

+1

नोट किया गया, और बदला गया। धन्यवाद! – rlbond

+2

क्या मैं पूछ सकता हूं कि आपको इसके लिए पुनरावृत्ति की आवश्यकता है? हो सकता है कि इसके बजाय ऐसा करने के लिए "वेक्टरकृत" तरीका हो ... –

उत्तर

78

आप प्रत्येक तत्व तक पहुंचने के लिए रैखिक अनुक्रमण का उपयोग कर सकते हैं।

for idx = 1:numel(array) 
    element = array(idx) 
    .... 
end 

अगर आप को पता है कि i, j, k, तो आप कर रहे हैं की जरूरत नहीं है उपयोगी है। हालांकि, अगर आपको यह जानने की आवश्यकता नहीं है कि आप किस इंडेक्स पर हैं, तो आप शायद arrayfun()

+1

इसके अलावा, अगर आप किसी कारण से सूचकांक पुनर्प्राप्त करना चाहते हैं, तो भी आप इन दो सरल आदेशों का उपयोग कर सकते हैं: 'I = सेल (1, ndims (सरणी)); [मैं {:}] = ind2sub (आकार (सरणी), idx); '। – knedlsepp

-1

यदि आप size के अन्य उपयोगों में गहराई से देखते हैं तो आप देख सकते हैं कि आप वास्तव में प्रत्येक आयाम के आकार का वेक्टर प्राप्त कर सकते हैं। यह लिंक आपको प्रलेखन पता चलता है:

www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html

आकार वेक्टर मिलने के बाद, कि वेक्टर से अधिक पुनरावृति। कुछ इस तरह (मेरे वाक्य रचना क्षमा के बाद से मैं कॉलेज के बाद से मैटलैब इस्तेमाल नहीं किया है):

d = size(m); 
dims = ndims(m); 
for dimNumber = 1:dims 
    for i = 1:d[dimNumber] 
     ... 

वास्तविक मैटलैब-कानूनी वाक्य विन्यास में इस करते हैं, और मुझे लगता है कि आप क्या चाहते हैं करना होगा।

इसके अलावा, आपको here वर्णित रैखिक इंडेक्सिंग करने में सक्षम होना चाहिए।

+0

मैं बिल्कुल नहीं देख सकता कि लूप का ऑर्डर मैट्रिक्स के सभी तत्वों पर फिर से चालू होगा। उदाहरण के लिए, यदि आपके पास 3-बाय -4 मैट्रिक्स (12 तत्वों के साथ) है, तो आपका आंतरिक पाश केवल 7 बार पुनरावृत्त होगा। – gnovice

+0

यह मैट्रिक्स के प्रत्येक आयाम पर फिर से शुरू होना चाहिए। वह बाहरी लूप आयाम पर, उस आयाम के आकार पर भीतरी पाश पर पुनरावृत्त करता है। कम से कम, यह विचार है। जैसा कि हर कोई बता रहा है, अगर वह चाहता है कि प्रत्येक सेल है, लाइनर इंडेक्सिंग सबसे अच्छा है। यदि वह प्रत्येक आयाम पर फिर से शुरू करना चाहता है, तो उसे ऐसा कुछ करना होगा। –

+0

भी, संपादन के लिए धन्यवाद। मेरा लिंक थोड़े से घिरा हुआ था और सामान्य लिंकिंग तरीके से सही काम नहीं करेगा। इसके अलावा, मेरे बयान का विस्तार करने के लिए: उसे अभी भी इंडेक्स की कई अन्य ट्रैकिंग करना होगा (काउंटर या ऐसा कुछ इस्तेमाल करना)। मुझे लगता है कि आप या एंड्रयू का दृष्टिकोण आसान होगा जो मुझे लगता है कि वह ऐसा करने की कोशिश कर रहा है। –

32

मैटलैब में सरणी के लिए रैखिक अनुक्रमणिका का विचार एक महत्वपूर्ण है। MATLAB में एक सरणी वास्तव में तत्वों का एक वेक्टर है, जो स्मृति में बाहर निकलती है। MATLAB आपको या तो पंक्ति और कॉलम अनुक्रमणिका या एकल रैखिक अनुक्रमणिका का उपयोग करने की अनुमति देता है। उदाहरण के लिए,

A = magic(3) 
A = 
    8  1  6 
    3  5  7 
    4  9  2 

A(2,3) 
ans = 
    7 

A(8) 
ans = 
    7 

हम तत्वों एक वेक्टर में सरणी unrolling द्वारा स्मृति में जमा हो जाती है देख सकते हैं।

A(:) 
ans = 
    8 
    3 
    4 
    1 
    5 
    9 
    6 
    7 
    2 

जैसा कि आप देख सकते हैं, 8 वें तत्व संख्या 7 है। वास्तव में, फ़ंक्शन एक रैखिक अनुक्रमणिका के रूप में अपने परिणाम लौटाता है।

find(A>6) 
ans = 
    1 
    6 
    8 

परिणाम यह है कि हम एक एकल लूप का उपयोग करके सामान्य एन-डी सरणी के बदले प्रत्येक तत्व को एक्सेस कर सकते हैं। उदाहरण के लिए, अगर हम (हाँ, मुझे पता है कि बेहतर तरीके यह करने के लिए कर रहे हैं) एक के तत्वों वर्ग चाहता था, एक ऐसा करने दे सकता है:

B = zeros(size(A)); 
for i = 1:numel(A) 
    B(i) = A(i).^2; 
end 

B 
B = 
    64  1 36 
    9 25 49 
    16 81  4 

कई परिस्थितियों रहे हैं जहां रैखिक सूचकांक अधिक उपयोगी है। रैखिक सूचकांक और दो (या उच्च) आयामी सबस्क्रिप्ट के बीच रूपांतरण sub2ind और ind2sub कार्यों के साथ पूरा किया जाता है।

रैखिक सूचकांक सामान्य रूप से matlab में किसी भी सरणी पर लागू होता है। तो आप इसे संरचनाओं, सेल सरणी आदि पर उपयोग कर सकते हैं। रैखिक सूचकांक के साथ एकमात्र समस्या तब होती है जब वे बहुत बड़े होते हैं। MATLAB इन इंडेक्स को स्टोर करने के लिए 32 बिट पूर्णांक का उपयोग करता है। तो यदि आपके सरणी में कुल 2^32 तत्व हैं, तो रैखिक सूचकांक विफल हो जाएगा। यह वास्तव में केवल एक मुद्दा है यदि आप अक्सर स्पैर मैट्रिक्स का उपयोग करते हैं, जब कभी-कभी इससे कोई समस्या आती है। (हालांकि मैं 64 बिट MATLAB रिलीज का उपयोग नहीं करता, मुझे विश्वास है कि उन भाग्यशाली व्यक्तियों के लिए समस्या हल हो गई है जो करते हैं।)

+0

64-बिट MATLAB में इंडेक्सिंग वास्तव में 64-बिट सबस्क्रिप्ट को सही ढंग से अनुमति देता है। उदाहरण के लिए: 'x = ones (1,2^33, 'uint8'); एक्स (2^33) 'अपेक्षित काम करता है। – Edric

+0

@Edric - बेशक, यह एक ऐसा व्यवहार है जो निश्चित रूप से वर्षों (और कई रिलीज) में बदल गया होगा क्योंकि मैंने यह बयान दिया था। हालांकि जांच के लिए धन्यवाद। –

+0

:) मुझे एहसास नहीं हुआ कि जब तक मैंने टिप्पणी की थी तब तक जवाब कितना पुराना था - प्रश्न सिर्फ मेरे आरएसएस फ़ीड में दिखाई दिया, और मैंने यह भी ध्यान नहीं दिया कि मैंने इसका उत्तर भी दिया होगा! MATLAB को बतख टाइपिंग कैसे करता है इसका एक अच्छा उदाहरण दिखाने के लिए – Edric

15

के रूप में कुछ अन्य उत्तर में बताया, तुम पर सभी तत्वों को एक मैट्रिक्स एक (किसी भी आयाम की) से एक रेखीय सूचकांक का उपयोग करने में numel (ए) करने के लिए एक एकल में पुनरावृति कर सकते हैं पाश। कुछ अन्य चालें आप उपयोग कर सकते हैं: ARRAYFUN और CELLFUN

आइए पहले मान लें कि आपके पास एक ऐसा कार्य है जिसे आप (जिसे "my_func" कहा जाता है) के प्रत्येक तत्व पर लागू करना चाहते हैं। आप पहली बार इस समारोह के लिए एक function handle बनाएँ:

fcn = @my_func; 

तो एक मनमाना आयाम (प्रकार पर दो, एकल, आदि की) एक मैट्रिक्स है, तो आप उपयोग कर सकते हैं ARRAYFUN प्रत्येक तत्व के लिए "my_func" लागू करने के लिए:

outArgs = cellfun(fcn,A); 
:

outArgs = arrayfun(fcn,A); 

तो एक मनमाना आयाम के एक सेल सरणी है, तो आप प्रत्येक कोशिका के लिए "my_func" लागू करने के लिए उपयोग कर सकते हैं CELLFUN 0

फ़ंक्शन "my_func" को इनपुट के रूप में स्वीकार करना होगा। यदि "my_func" से कोई आउटपुट हैं, तो इन्हें आउटअर्स में रखा गया है, जो के समान आकार/आयाम होगा। आउटपुट पर

एक चेतावनी ... अगर "my_func" रिटर्न अलग आकार और प्रकार के आउटपुट जब यह के विभिन्न तत्वों पर चल रही एक, तो outArgs एक सेल सरणी में किए जाने के लिए होगा। यह एक अतिरिक्त पैरामीटर/मूल्य जोड़ी के साथ या तो ARRAYFUN या CELLFUN बुला द्वारा किया जाता है:

outArgs = arrayfun(fcn,A,'UniformOutput',false); 
outArgs = cellfun(fcn,A,'UniformOutput',false); 
13

एक अन्य चाल ind2sub और sub2ind उपयोग करने के लिए है। numel और size साथ संयोजन के रूप में, यह कर सकते हैं आप निम्नलिखित है, जो एक एन आयामी सरणी बनाता है, और उसके बाद की तरह सामान करना "विकर्ण" पर सभी तत्वों सेट होने के लिए 1.

d = zeros(3, 4, 5, 6); % Let's pretend this is a user input 
nel = numel(d); 
sz = size(d); 
szargs = cell(1, ndims(d)); % We'll use this with ind2sub in the loop 
for ii=1:nel 
    [ szargs{:} ] = ind2sub(sz, ii); % Convert linear index back to subscripts 
    if all([szargs{2:end}] == szargs{1}) % On the diagonal? 
     d(ii) = 1; 
    end 
end 
+0

+1 इंड 2 एसयूबी और सब 2ind – catchmeifyoutry

+0

+1 के लिए +1। –

-1

आप करना चाहते हैं loops के लिए n-nested अनुकरण।

एन-डिमेंमेंटल सरणी के माध्यम से इटरेटिंग को एन-अंक संख्या बढ़ाने के रूप में देखा जा सकता है।

प्रत्येक आयाम पर हमारे पास आयाम की लंबाई के रूप में कई अंक हैं।

उदाहरण:

मान लीजिए हम था सरणी (मैट्रिक्स)

int[][][] T=new int[3][4][5]; 
में

"अंकन के लिए" हमने:

for(int x=0;x<3;x++) 
    for(int y=0;y<4;y++) 
     for(int z=0;z<5;z++) 
      T[x][y][z]=... 

इस अनुकरण करने के लिए आप "n का उपयोग करना होगा -डिजिट संख्या नोटेशन "

हमारे पास 3 अंक हैं, पहले के लिए 3 अंक, दूसरे के लिए 4 और पांच के लिए पांच तृतीय अंकों

हम संख्या में वृद्धि करने के लिए है, इसलिए हम अनुक्रम

0 0 0 
0 0 1 
0 0 2  
0 0 3 
0 0 4 
0 1 0 
0 1 1 
0 1 2 
0 1 3 
0 1 4 
0 2 0 
0 2 1 
0 2 2 
0 2 3 
0 2 4 
0 3 0 
0 3 1 
0 3 2 
0 3 3 
0 3 4 
and so on 

मिलता तो आप इस तरह के n अंकों की संख्या को बढ़ाने के लिए कोड लिख सकते हैं होगा। आप इसे इस तरह से कर सकते हैं कि आप संख्या के किसी भी मूल्य से शुरू कर सकते हैं और अंकों को किसी भी संख्या से बढ़ा/घटा सकते हैं। इस तरह आप लूप के लिए नेस्टेड अनुकरण कर सकते हैं जो टेबल में कहीं से शुरू होता है और अंत में खत्म नहीं होता है।

हालांकि यह एक आसान काम नहीं है। मैं matlab नोटेशन दुर्भाग्य से मदद नहीं कर सकता।

1

आप

  • L = size(M)
  • idx = zeros(L,1)
  • अधिकतम गहराई के रूप में length(L) लो
  • लूप for idx(depth) = 1:L(depth)
  • यदि आपका गहराई length(L) है चलो चलो कर सकता है एक पुनरावर्ती समारोह काम करते हैं, करते हैं तत्व ऑपरेशन, अन्यथा फिर से फ़ंक्शन को depth+1
  • के साथ कॉल करें

यदि आप सभी बिंदुओं को देखना चाहते हैं तो वेक्टरकृत विधियों जितनी जल्दी नहीं हो, लेकिन यदि आपको उनमें से अधिकतर का मूल्यांकन करने की आवश्यकता नहीं है तो यह काफी समय बचा सकता है।

1

इन समाधानों numel का उपयोग कर अधिक से अधिक तेजी से (लगभग 11%) कर रहे हैं;)

for idx = reshape(array,1,[]), 
    element = element + idx; 
end 

या

for idx = array(:)', 
    element = element + idx; 
end 

युपीडी। पिछले जवाब में पाया त्रुटि के लिए tnx @rayryeng


अस्वीकरण

समय जानकारी है कि इस पोस्ट संदर्भित है एक मौलिक टाइपो कि बनाया गया था की वजह से गलत और गलत है (और साथ ही नीचे टिप्पणी स्ट्रीम देख edit history - विशेष रूप से इस उत्तर के पहले संस्करण को देखें)। Caveat Emptor

+1

'1: सरणी (:)' '1: सरणी (1)' के बराबर है। यह सभी तत्वों के माध्यम से पुनरावृत्ति नहीं करता है, यही कारण है कि आपके रन-टाइम त्वरित हैं। इसके अलावा, 'रैंड' ** फ़्लोटिंग-पॉइंट ** संख्याएं उत्पन्न करता है, और इसलिए '1: सरणी (:)' एक खाली सरणी उत्पन्न करेगा क्योंकि आपका कथन एक शुरुआती मूल्य के साथ एक प्रारंभिक मान के साथ एक बढ़ते वेक्टर को खोजने के लिए प्रयास कर रहा है 1 के बढ़ते चरणों में 1 [1,1,1) 'की एक सीमा के साथ एक फ्लोटिंग पॉइंट नंबर के रूप में मूल्य 1. ऐसा कोई संभावित वेक्टर नहीं है, जिसके परिणामस्वरूप खाली वेक्टर होता है। आपका 'लूप' नहीं चलता है, और इसलिए आपका दावा गलत है। -1 वोट माफ़ कीजिये। – rayryeng

+0

@rayryeng आप सही नहीं हैं। सरणी (:) 1 के बराबर नहीं है: सरणी (1)। इसे 'reshape (...)' पसंद है। – mathcow

+0

मैंने बस MATLAB में वह कोड चलाया। यह काम नहीं करता है। – rayryeng