2016-03-11 3 views
5

मैं Matlab में निम्नलिखित मैट्रिक्स:एक मैट्रिक्स के प्रत्येक पंक्ति में 1 के लिए स्तंभ अनुक्रमणिका ढूँढना

M = [0 0 1 
    1 0 0 
    0 1 0 
    1 0 0 
    0 0 1]; 

प्रत्येक पंक्ति है ठीक एक 1. मैं (पाशन के बिना) तो एक स्तंभ वेक्टर निर्धारित कर सकते हैं कि पहला तत्व 2 है यदि दूसरे कॉलम में 1 है, तो दूसरा तत्व तीसरे कॉलम इत्यादि में से एक के लिए 3 है?

M = [ 3 
     1 
     2 
     1 
     3]; 

उत्तर

5

आप वास्तव में सरल आव्यूह गुणन के साथ इस का समाधान कर सकते हैं: ऊपर के उदाहरण में बदल देना चाहिए।

result = M * (1:size(M, 2)).'; 

    3 
    1 
    2 
    1 
    3 

यह एक 3 एक्स 1 सरणी जहां 3x1 के तत्वों बस रहे हैं [1; 2; 3] के साथ अपने एम एक्स 3 मैट्रिक्स गुणा करके काम करता है। संक्षेप में, M की प्रत्येक पंक्ति के लिए, तत्व-वार गुणा 3 x 1 सरणी के साथ किया जाता है। केवल M की पंक्ति में 1 परिणाम परिणाम में कुछ भी प्रदान करेगा। फिर इस तत्व-वार गुणा के परिणाम का सारांश दिया जाता है। क्योंकि आपके पास प्रति पंक्ति केवल एक "1" है, परिणाम कॉलम इंडेक्स होने जा रहा है जहां वह 1 स्थित है।

तो उदाहरण के लिए M की पहली पंक्ति के लिए।

element_wise_multiplication = [0 0 1] .* [1 2 3] 

    [0, 0, 3] 

sum(element_wise_multiplication) 

    3 

अद्यतन

@reyryeng और नीचे @Luis द्वारा प्रदान समाधान के आधार पर, मैं एक तुलना चलाने के लिए कैसे विभिन्न तरीकों के प्रदर्शन की तुलना में देखने का फैसला किया।

परीक्षण मैट्रिक्स (M) सेट अप करने के लिए मैंने मूल प्रश्न में निर्दिष्ट फॉर्म का एक मैट्रिक्स बनाया और पंक्तियों की संख्या को अलग किया। किस कॉलम कोका उपयोग करके यादृच्छिक रूप से चुना गया था। निष्पादन के समय का विश्लेषण का उपयोग करके किया गया था।

double (MATLAB के डिफ़ॉल्ट) के प्रकार का उपयोग करते समय चलाते समय आपको निम्नलिखित निष्पादन समय मिलते हैं।

enter image description here

तो M एक logical है, तो आव्यूह गुणन तथ्य यह है कि यह एक संख्यात्मक प्रकार गुणा मैट्रिक्स से पहले करने के लिए परिवर्तित किया गया है अन्य दो एक का एक सा है, जबकि की वजह से एक हिट लेता है प्रदर्शन में सुधार।

enter image description here

यहाँ परीक्षण कोड है कि मैं का इस्तेमाल किया है।

sizes = round(linspace(100, 100000, 100)); 
times = zeros(numel(sizes), 3); 

for k = 1:numel(sizes) 
    M = generateM(sizes(k)); 
    times(k,1) = timeit(@()M * (1:size(M, 2)).'); 
    M = generateM(sizes(k)); 
    times(k,2) = timeit(@()max(M, [], 2), 2); 
    M = generateM(sizes(k)); 
    times(k,3) = timeit(@()find(M.'), 2); 
end 

figure 
plot(range, times/1000); 
legend({'Multiplication', 'Max', 'Find'}) 
xlabel('Number of rows in M') 
ylabel('Execution Time (ms)') 

function M = generateM(nRows) 
    M = zeros(nRows, 3); 
    col = randi([1 size(M, 2)], 1, size(M, 1)); 
    M(sub2ind(size(M), 1:numel(col), col)) = 1; 
end 
+0

आपके बहुत तेज़ उत्तर के लिए बहुत बहुत धन्यवाद। ये बिलकुल सही है। – machinery

2

तुम भी find दुरुपयोग और पंक्ति M की पक्षांतरित की पदों का निरीक्षण कर सकते हैं। आप पहली बार मैट्रिक्स स्थानांतरित करने के लिए के रूप में find स्तंभ प्रमुख क्रम में चल रही है:

M = [0 0 1 
    1 0 0 
    0 1 0 
    1 0 0 
    0 0 1]; 

[out,~] = find(M.'); 

अगर यह आव्यूह गुणन की तुलना में तेजी है, हालांकि सुनिश्चित नहीं हैं।

+1

'ढूंढ' दुर्लभ मौकों में से एक है जहां '[बाहर, ~] = ...' '= =' –

+0

@LuisMendo आह हाँ सर के समान नहीं है! – rayryeng

2

फिर भी एक और दृष्टिकोण: max की दूसरी उत्पादन का उपयोग करें: के रूप में @rayryeng ने सुझाव दिया

[~, result] = max(M.', [], 1); 

या, maxM transposing के बजाय का उपयोग दूसरे आयाम के साथ:

[~, result] = max(M, [], 2); 

के लिए
M = [0 0 1 
    1 0 0 
    0 1 0 
    1 0 0 
    0 0 1]; 

इस देता है

result = 
    3  1  2  1  3 

तो M किसी पंक्ति में एक से अधिक 1 होता है, यह इस तरह की पहली 1 के सूचकांक दे देंगे।

+0

अच्छी तरह से किया गया। मैं हमेशा इस तरह 'अधिकतम' का उपयोग करने के बारे में भूल जाते हैं। मुझे आश्चर्य है कि सभी दृष्टिकोणों के बीच प्रदर्शन तुलना क्या है। मेरा पैसा 'अधिकतम' – rayryeng

+2

पर है यदि आपने मैट्रिक्स को स्थानांतरित नहीं किया है और इसके बजाय मैट्रिक्स की पंक्तियों के साथ निर्दिष्ट निर्दिष्ट किया है तो क्या कोई प्रदर्शन अंतर है? '2' होने के लिए आयाम निर्दिष्ट करने की तरह? – rayryeng

+0

@rayryeng अच्छा बिंदु। संभवतः तेजी से स्थानांतरित नहीं करना, हां –

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