2012-12-07 21 views
7

मुझे सभी तीन तत्व त्रिकोणों को पकड़ने की आवश्यकता है जो एक सममित मैट्रिक्स के निचले त्रिकोण को बनाते हैं। मैं इस बात को नहीं सोच सकता कि नीचे दिए गए बाएं कॉलम के क्रम में इन सभी टुकड़ों को कैसे पकड़ें और फिर दाईं ओर के अगले कॉलम को और कैसे चालू करें। मुझे पता है कि कट्टरपंथी घुड़दौड़ का घोड़ा ROF कम त्रिकोण के अंदर मिनी त्रिकोण है:निचले त्रिकोण के भीतर त्रिभुजों को पकड़ें

n = x(x - 1)/2 
where: x = nrow(mats[[i]]) 

यहाँ मैं पत्र (यह आसान मुझे इस तरह की अवधारणा के लिए है) और व्यवस्था मैं कर रहा हूँ में तत्वों के साथ तीन मैट्रिक्स बना लिया है की तलाश में:

list(c("B", "C", "F")) 

list(c("B", "C", "G"), c("C", "D", "H"), c("G", "H", "L")) 

list(c("B", "C", "H"), c("C", "D", "I"), c("D", "E", "J"), 
    c("H", "I", "N"), c("I", "J", "O"), c("N", "O", "T")) 

कैसे कर सकते हैं मैं:

FUN <- function(n) { 
    matrix(LETTERS[1:(n*n)], n) 
} 

mats <- lapply(3:5, FUN) 

तो यह उत्पादन मैं (मैं नहीं बल्कि उत्पादन प्रारूप से कोड में रख) ऊपर बनाया मैट्रिक्स से प्रत्येक के लिए प्राप्त करना चाहते हैं है टी करो बेस आर में रहने के दौरान सबसे तेज़ तरीके से अपना काम संभव है?

सुनिश्चित नहीं हैं कि मैं क्या कर रहा हूँ के बाद से उपयोगी है के इस दृश्य लेकिन यह हो सकता है:

enter image description here

+0

एक 5x5 मैट्रिक्स सबसे बड़ा है कि आप उम्मीद करेंगे परीक्षण करने के लिए है करने के लिए है? –

+0

नहीं, यह बड़ा हो सकता है (हालांकि मुझे संदेह है कि यह कभी भी बड़ा होगा)। –

+0

@ टायलर रिंकर - मुझे 10K * 10K मैट्रिक्स पर कुछ बेंचमार्किंग का प्रयास करते समय बस मेरे आर सत्र को मजबूर करना पड़ा। 1 के * 1 के कुछ सेकंड का मामला था। मुझे आश्चर्य है कि वहां के लोगों के पास अधिक कुशल कार्यान्वयन हो सकते हैं। – thelatemail

उत्तर

5

अच्छा समस्या! यहाँ आप यह कैसे एक (एक बहुत सरल संस्करण के बाद)

triangle <- function(base.idx, mat) { 
    upper.idx <- base.idx - 1L 
    right.idx <- base.idx + nrow(mat) 
    paste(mat[c(upper.idx, base.idx, right.idx)], collapse = " ") 
} 

get.triangles <- function(mat) { 
    N <- nrow(mat) 
    if (N == 3L) { 
     return(triangle(3L, mat)) 
    } else { 
     left.idx <- 3:N 
     right.mat <- mat[2:N, 2:N] 
     left.triangles <- sapply(left.idx, triangle, mat) 
     right.triangles <- Recall(right.mat) 
     return(c(left.triangles, right.triangles)) 
    } 
} 

x <- lapply(mats, get.triangles) 

# [[1]] 
# [1] "B C F" 
# 
# [[2]] 
# [1] "B C G" "C D H" "G H L" 
# 
# [[3]] 
# [1] "B C H" "C D I" "D E J" "H I N" "I J O" "N O T" 

प्रत्यावर्तन की बिट मैं सिर्फ उत्पादन बिल्कुल न होने के लिए कहा पर टिप्पणी करेंगे का उपयोग कर हल कर सकते है। यह इसलिए क्योंकि पुनरावर्ती कार्यों कि एक फ्लैट सूची लौट हमेशा के साथ काम करना मुश्किल है बनाने: किसी भी तरह आप हमेशा नेस्टेड सूची के साथ अंत ...

तो अंतिम चरण होना चाहिए:

lapply(x, strsplit, split = " ") 

और कहीं भी होगी उसी प्रारूप में रहें जिसके लिए आपने पूछा था।

असल में, इस विधि हो जाता है:


और यहाँ

get.triangles <- function(mat) { 
    base.idx <- seq_along(mat)[row(mat) > col(mat) + 1] 
    upper.idx <- base.idx - 1L 
    right.idx <- base.idx + nrow(mat) 

    lapply(mapply(c, upper.idx, base.idx, right.idx, SIMPLIFY = FALSE), 
      function(i)mat[i]) 
} 
+0

आपको धन्यवाद जो बहुत अच्छी तरह से काम करता है। मैं बिना किसी घुसपैठ के विधि का उपयोग करूंगा क्योंकि 'strsplit' का उपयोग करने की कोई आवश्यकता नहीं है (और यदि यह संख्यात्मक मैट्रिक्स को 'as.numeric'' का उपयोग करने की आवश्यकता नहीं है)। +1 –

3

एक SIMPLIFY=FALSE जोड़ने के लिए संपादित जो अब देता है आप अपनी ज़रुरत के एक और भी सरल संस्करण (प्रत्यावर्तन के बारे में भूल!) है त्रिकोणों के सभी शीर्ष बाएं कोनों की अनुक्रमणिका जो आप चाहते हैं और फिर [नीचे सेल] + [नीचे से नीचे + सेल] पकड़ लेते हैं। रोमांच। इस विधि का एक अतिरिक्त लाभ यह है कि यह matrix और data.frame ऑब्जेक्ट्स के लिए काम करता है।

bot.tris <- function(data) { 
    idx1 <- unlist(sapply((nrow(data)-2):1,function(x) tail(2:(nrow(data)-1),x))) 
    idx2 <- rep(1:(nrow(data)-2),(nrow(data)-2):1) 
    mapply(function(x,y) {c(data[x,y],data[x+1,y],data[x+1,y+1])},idx1,idx2,SIMPLIFY=FALSE) 
} 

और परिणाम:

> result <- lapply(mats,bot.tris) 
> str(result) 
List of 3 
$ :List of 1 
    ..$ : chr [1:3] "B" "C" "F" 
$ :List of 3 
    ..$ : chr [1:3] "B" "C" "G" 
    ..$ : chr [1:3] "C" "D" "H" 
    ..$ : chr [1:3] "G" "H" "L" 
$ :List of 6 
    ..$ : chr [1:3] "B" "C" "H" 
    ..$ : chr [1:3] "C" "D" "I" 
    ..$ : chr [1:3] "D" "E" "J" 
    ..$ : chr [1:3] "H" "I" "N" 
    ..$ : chr [1:3] "I" "J" "O" 
    ..$ : chr [1:3] "N" "O" "T" 
+1

यह दृष्टिकोण निश्चित रूप से कम कोडिंग और समझने में बहुत आसान है।मैंने दोनों प्रतिक्रियाओं और flodel बेंचमार्क किया है तेजी से। यहां दोनों कार्य मेरे पास (कुछ भी नहीं) की तुलना में तेज़ हैं। समस्या से निपटने के लिए बहुत कुछ धन्यवाद। +1 –

+0

* "यहां दोनों कार्य मेरे पास जो कुछ भी था (कुछ नहीं) से तेज़ हैं" * - मुझे यह पसंद है :-) – thelatemail

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