खोज…


उपयोगी कार्य जो कोशिकाओं और सरणियों पर संचालित होते हैं

यह सरल उदाहरण कुछ कार्यों पर एक स्पष्टीकरण प्रदान करता है जो मुझे बेहद उपयोगी लगे क्योंकि मैंने MATLAB का उपयोग करना शुरू कर दिया है: cellfun , arrayfun । विचार अपने सभी तत्वों के माध्यम से एक सरणी या सेल वर्ग चर, लूप लेने और प्रत्येक तत्व पर एक समर्पित फ़ंक्शन लागू करना है। एक लागू फ़ंक्शन या तो अनाम हो सकता है, जो आमतौर पर एक मामला है, या * .m फ़ाइल में कोई भी नियमित फ़ंक्शन परिभाषित होता है।

आइए एक साधारण समस्या से शुरू करते हैं और कहते हैं कि हमें फ़ोल्डर की * .mat फ़ाइलों की सूची खोजने की आवश्यकता है। इस उदाहरण के लिए, पहले एक मौजूदा फ़ोल्डर में कुछ * .mat फाइलें बनाते हैं:

for n=1:10; save(sprintf('mymatfile%d.mat',n)); end

कोड निष्पादित करने के बाद, एक्सटेंशन * .mat के साथ 10 नई फाइलें होनी चाहिए। यदि हम सभी * .mat फ़ाइलों को सूचीबद्ध करने के लिए एक कमांड चलाते हैं, जैसे:

mydir = dir('*.mat');

हमें एक dir संरचना के तत्वों की एक सरणी मिलनी चाहिए; MATLAB को इसी तरह का आउटपुट देना चाहिए:

10x1 struct array with fields:
    name
    date
    bytes
    isdir
    datenum

जैसा कि आप देख सकते हैं कि इस सरणी का प्रत्येक तत्व दो क्षेत्रों के साथ एक संरचना है। सभी जानकारी वास्तव में प्रत्येक फ़ाइल के बारे में महत्वपूर्ण हैं, लेकिन 99% में मुझे फ़ाइल नामों में दिलचस्पी है और कुछ नहीं। संरचना सरणी से जानकारी निकालने के लिए, मैं एक स्थानीय फ़ंक्शन बनाता था जिसमें एक सही आकार के लौकिक चर बनाना शामिल होगा, लूप के लिए, प्रत्येक तत्व से एक नाम निकालना, और इसे बनाए गए चर में सहेजना। ठीक उसी परिणाम को प्राप्त करने के लिए बहुत आसान तरीका है उपरोक्त कार्यों में से एक का उपयोग करना:

mydirlist = arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false)
mydirlist = 
    'mymatfile1.mat'
    'mymatfile10.mat'
    'mymatfile2.mat'
    'mymatfile3.mat'
    'mymatfile4.mat'
    'mymatfile5.mat'
    'mymatfile6.mat'
    'mymatfile7.mat'
    'mymatfile8.mat'
    'mymatfile9.mat'

यह फ़ंक्शन कैसे काम करता है? यह आमतौर पर दो पैरामीटर लेता है: पहला पैरामीटर और एक सरणी के रूप में एक फ़ंक्शन हैंडल। एक फ़ंक्शन दिए गए सरणी के प्रत्येक तत्व पर काम करेगा। तीसरा और चौथा पैरामीटर वैकल्पिक लेकिन महत्वपूर्ण हैं। यदि हम जानते हैं कि एक आउटपुट नियमित नहीं होगा, तो इसे सेल में सहेजा जाना चाहिए। यह UniformOutput लिए false होना चाहिए। डिफ़ॉल्ट रूप से यह फ़ंक्शन संख्याओं के वेक्टर जैसे एक नियमित आउटपुट को वापस करने का प्रयास करता है। उदाहरण के लिए, आइए जानकारी निकालें कि बाइट में प्रत्येक फ़ाइल द्वारा कितना डिस्क स्थान लिया गया है:

mydirbytes = arrayfun(@(x) x.bytes, dir('*.mat'))
mydirbytes =
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560

या किलोबाइट्स:

mydirbytes = arrayfun(@(x) x.bytes/1024, dir('*.mat'))
mydirbytes =
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500

इस बार आउटपुट डबल का नियमित वेक्टर है। डिफ़ॉल्ट रूप से UniformOutput को true सेट किया गया था।

cellfun एक समान कार्य है। इस फ़ंक्शन और arrayfun बीच का अंतर यह है कि cellfun सेल क्लास चर पर संचालित होता है। यदि हम किसी सेल 'mydirlist' में केवल फ़ाइल नामों की एक सूची दिए गए नामों को निकालना चाहते हैं, तो हमें इस फ़ंक्शन को निम्न प्रकार से चलाने की आवश्यकता होगी:

mydirnames = cellfun(@(x) x(1:end-4), mydirlist, 'UniformOutput', false)
mydirnames = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

फिर से, चूंकि आउटपुट संख्याओं का एक नियमित वेक्टर नहीं है, इसलिए आउटपुट को सेल चर में सहेजा जाना चाहिए।

नीचे दिए गए उदाहरण में, मैं दो कार्यों को एक में संयोजित करता हूं और बिना एक्सटेंशन के केवल फ़ाइल नामों की सूची लौटाता हूं:

cellfun(@(x) x(1:end-4), arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false), 'UniformOutput', false)
ans = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

यह पागल है लेकिन बहुत संभव है क्योंकि arrayfun एक सेल देता है जो cellfun का अपेक्षित इनपुट है; इसका एक साइड नोट यह है कि हम उन सभी कार्यों में से किसी को भी सेल वेरिएबल में परिणाम देने के लिए मजबूर कर सकते हैं ताकि UniformOutput को गलत, स्पष्ट रूप से सेट किया जा UniformOutput । हम हमेशा एक सेल में परिणाम प्राप्त कर सकते हैं। हम नियमित वेक्टर में परिणाम प्राप्त करने में सक्षम नहीं हो सकते हैं।

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

structfun(@(x) ischar(x), mydir(1))

एक dir संरचना का पहला और दूसरा क्षेत्र चार प्रकार का है। इसलिए, आउटपुट है:

 1
 1
 0
 0
 0

साथ ही, आउटपुट true / false का एक तार्किक वेक्टर है। नतीजतन, यह नियमित है और इसे एक वेक्टर में बचाया जा सकता है; सेल वर्ग का उपयोग करने की आवश्यकता नहीं है।

कोड तह वरीयताएँ

अपनी आवश्यकता के अनुरूप कोड तह वरीयता को बदलना संभव है। इस प्रकार कोड तह को विशिष्ट निर्माणों के लिए सक्षम / अक्षम किया जा सकता है (उदा: if block , for loop , Sections ...)।

तह वरीयताओं को बदलने के लिए, वरीयताएँ पर जाएँ -> कोड तह:

यहाँ छवि विवरण दर्ज करें

फिर आप चुन सकते हैं कि कोड के किस भाग को मोड़ा जा सकता है।

कुछ जानकारी:

  • ध्यान दें कि आप अपने कर्सर को फ़ाइल के भीतर कहीं भी रखकर किसी फ़ाइल में सभी कोड का विस्तार या पतन कर सकते हैं, राइट-क्लिक करें, और फिर कोड तह> विस्तार सभी या कोड तह> संदर्भ मेनू से सभी को फोल्ड करें का चयन करें।
  • ध्यान दें कि तह लगातार है, इस अर्थ में कि कोड का वह हिस्सा जो विस्तारित / ध्वस्त हो गया है, Matlab या m-file को बंद कर दिया गया है और फिर से खुला होने के बाद अपनी स्थिति बनाए रखेगा।

उदाहरण: वर्गों के लिए तह सक्षम करने के लिए:

एक दिलचस्प विकल्प अनुभागों को मोड़ना सक्षम करना है। अनुभागों को दो प्रतिशत संकेतों ( %% ) द्वारा सीमांकित किया गया है।

उदाहरण: इसे सक्षम करने के लिए "अनुभाग" बॉक्स देखें:

यहाँ छवि विवरण दर्ज करें

फिर एक समान स्रोत कोड देखने के बजाय:

यहाँ छवि विवरण दर्ज करें

आप अपने कोड का सामान्य अवलोकन करने के लिए वर्गों को मोड़ने में सक्षम होंगे: यहाँ छवि विवरण दर्ज करें

आंकड़ा आंकड़ा निकालें

कुछ अवसरों पर, मेरे पास एक दिलचस्प आंकड़ा था जिसे मैंने सहेजा था लेकिन मैंने इसके डेटा तक पहुंच खो दी। यह उदाहरण एक चाल दिखाता है कि किसी आकृति से निकालने की जानकारी कैसे प्राप्त की जाए।

प्रमुख कार्य खोजबोज और मिलते हैंfindobj किसी हैंडलर को किसी दिए गए गुण या वस्तु के गुण, जैसे कि Type या Color इत्यादि देता है। एक बार जब एक लाइन ऑब्जेक्ट मिल जाता है, तो गुणों द्वारा आयोजित किसी भी मूल्य को वापस कर सकता है। यह पता चलता है कि Line ऑब्जेक्ट्स निम्नलिखित गुणों में सभी डेटा XData हैं: XData , YData , और ZData ; जब तक किसी आकृति में 3D प्लॉट नहीं होता, तब तक अंतिम वाला आमतौर पर 0 होता है।

निम्न कोड एक उदाहरण आकृति बनाता है जो दो पंक्तियों को एक पाप कार्य और एक दहलीज और एक किंवदंती दिखाता है

t = (0:1/10:1-1/10)';
y = sin(2*pi*t);
plot(t,y);
hold on;
plot([0 0.9],[0 0], 'k-');
hold off;
legend({'sin' 'threshold'});

का पहला प्रयोग findobj रिटर्न दोनों लाइनों के लिए दो संचालकों:

findobj(gcf, 'Type', 'Line')
ans = 
  2x1 Line array:

  Line    (threshold)
  Line    (sin)

परिणाम संकीर्ण करने के लिए, findobj भी तार्किक ऑपरेटरों के संयोजन का उपयोग कर सकते हैं -and , -or और संपत्ति के नाम। उदाहरण के लिए, मैं एक लाइन ऑब्जेक्ट पा सकता हूं जिसका DiplayName sin और इसके XData और YData पढ़ YData

lineh = findobj(gcf, 'Type', 'Line', '-and', 'DisplayName', 'sin');
xdata = get(lineh, 'XData');
ydata = get(lineh, 'YData');

और जांचें कि क्या डेटा बराबर हैं।

isequal(t(:),xdata(:))
ans =
     1
isequal(y(:),ydata(:))
ans =
     1

इसी तरह, मैं काली रेखा (दहलीज) को छोड़कर अपने परिणामों को कम कर सकता हूं:

lineh = findobj(gcf, 'Type', 'Line', '-not', 'Color', 'k');
xdata = get(lineh, 'XData');
ydata = get(lineh, 'YData');

और अंतिम जांच इस बात की पुष्टि करती है कि इस आंकड़े से निकाले गए डेटा समान हैं:

isequal(t(:),xdata(:))
ans =
     1
isequal(y(:),ydata(:))
ans =
     1

बेनामी फ़ंक्शंस का उपयोग करके कार्यात्मक प्रोग्रामिंग

बेनामी कार्यों का उपयोग कार्यात्मक प्रोग्रामिंग के लिए किया जा सकता है। हल करने के लिए मुख्य समस्या यह है कि पुनरावृत्ति को लंगर डालने का कोई मूल तरीका नहीं है, लेकिन इसे अभी भी एक ही पंक्ति में लागू किया जा सकता है:

if_ = @(bool, tf) tf{2-bool}();

यह फ़ंक्शन एक बूलियन मान और दो फ़ंक्शन के सेल सरणी को स्वीकार करता है। यदि बूलियन मान सही के रूप में मूल्यांकन करता है, और दूसरा यदि बूलियन मान गलत के रूप में मूल्यांकन करता है, तो उन कार्यों में से पहला मूल्यांकन किया जाता है। अब हम आसानी से फैक्टरियल फंक्शन लिख सकते हैं:

fac = @(n,f) if_(n>1, {@()n*f(n-1,f), @()1});

यहां समस्या यह है कि हम सीधे एक पुनरावर्ती कॉल को आमंत्रित नहीं कर सकते हैं, क्योंकि दाहिने हाथ की ओर मूल्यांकन किए जाने पर फ़ंक्शन अभी तक एक चर को नहीं सौंपा गया है। हालाँकि हम इस कदम को लिख कर पूरा कर सकते हैं

factorial_ = @(n)fac(n,fac);

अब @(n)fac(n,fac) फैक्टरियल फ़ंक्शन को पुनरावर्ती रूप से विकसित करता है। वाई-कॉम्बिनेटर का उपयोग करके कार्यात्मक प्रोग्रामिंग में ऐसा करने का एक और तरीका, जिसे आसानी से लागू किया जा सकता है:

y_ = @(f)@(n)f(n,f);

इस उपकरण के साथ, फैक्टरियल फ़ंक्शन और भी छोटा है:

factorial_ = y_(fac);

या सीधे:

factorial_ = y_(@(n,f) if_(n>1, {@()n*f(n-1,f), @()1}));

एक ही .fig फ़ाइल में कई आंकड़े सहेजें

एक ग्राफिक्स ऐरे में कई फिगर हैंडल लगाकर, कई फिगर को एक ही .fig फाइल में सेव किया जा सकता है

h(1) = figure;
scatter(rand(1,100),rand(1,100));

h(2) = figure;
scatter(rand(1,100),rand(1,100));

h(3) = figure;
scatter(rand(1,100),rand(1,100));

savefig(h,'ThreeRandomScatterplots.fig');
close(h);

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

एक दिलचस्प पक्ष यह है कि आंकड़े उसी तरह व्यवस्थित रहेंगे, जब आप उन्हें खोलते हैं तो वे सहेजे गए थे।

टिप्पणी ब्लॉक करें

यदि आप अपने कोड का हिस्सा टिप्पणी करना चाहते हैं, तो टिप्पणी ब्लॉक उपयोगी हो सकते हैं। टिप्पणी ब्लॉक एक नई लाइन में %{ साथ शुरू होता है और %} साथ समाप्त होता है %} दूसरी नई पंक्ति में:

a = 10;
b = 3;
%{
c = a*b;
d = a-b;
%}

यह आपको उन अनुभागों को फोल्ड करने की अनुमति देता है जो आपने कोड को अधिक स्वच्छ और कॉम्पैक्ट बनाने के लिए टिप्पणी की थी।

ये ब्लॉक आपके कोड के चालू / बंद भागों के लिए भी उपयोगी हैं। ब्लॉक करने से पहले आपको ब्लॉक को जोड़ने के लिए एक और % जोड़ना होगा:

a = 10;
b = 3;
%%{ <-- another % over here
c = a*b;
d = a-b;
%}

कभी-कभी आप कोड के एक भाग पर टिप्पणी करना चाहते हैं, लेकिन इसके इंडेंटेशन को प्रभावित किए बिना:

for k = 1:a
    b = b*k;
    c = c-b;
    d = d*c;
    disp(b)
end

आमतौर पर, जब आप कोड के एक ब्लॉक को चिह्नित करते हैं और इसे टिप्पणी करने के लिए Ctrl + r दबाते हैं (तब तक स्वचालित रूप से सभी पंक्तियों में % जोड़कर, तब जब आप बाद में Ctrl + i को ऑटो इंडेंटेशन के लिए दबाते हैं, तो कोड का ब्लॉक अपने सही पदानुक्रम से चलता है जगह, और दाईं ओर बहुत अधिक स्थानांतरित:

for k = 1:a
    b = b*k;
    %     c = c-b;
    %     d = d*c;
    disp(b)
end

इसे हल करने का एक तरीका टिप्पणी ब्लॉक का उपयोग करना है, इसलिए ब्लॉक का अंदरूनी हिस्सा सही ढंग से इंडेंट रहता है:

for k = 1:a
    b = b*k;
    %{
    c = c-b;
    d = d*c;
    %}
    disp(b)
end


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow