2013-10-16 11 views
5

में Concat 2D Arrays आम तौर पर मैं दो 2 डी सरणी कैसे जोड़ सकता हूं?एफ #

let concatArrays (arr1:obj[,]) (arr2:obj[,]) = 
    ([arr1; arr2]) |> Array2d.concat 

इस समारोह does not है, हालांकि मौजूद हैं:

मेरे धारणा (मैं स्पष्ट रूप से आसानी से इस परीक्षण कर सकते हैं) है कि वे हमेशा स्तंभों की समान संख्या है। बस स्पष्ट होने के लिए, परिणाम को 2 डी सरणी लंबाई और योग की लंबाई और मूल arrays2D के समान कॉलम के साथ उत्पन्न करना चाहिए और इनपुट के समान प्रकार होना चाहिए, यहां obj [,]। मैं स्पष्ट रूप से इसे लूपिंग निर्माण में कर सकता था लेकिन मैं एक f # तरीके के बारे में सोच रहा था। धन्यवाद।

let append2D (arr1:float[,]) (arr2:float[,]) = 
    let cls = arr1.GetLength 1 
    let rows1 = arr1.GetLength 0 
    let rows2 = arr2.GetLength 0 
    Array2D.init (rows1+rows2) cls (fun i j -> match i with | a when a <= rows1 -> arr1.[i,j] | _ -> arr2.[i,j]) 

लेकिन इस सीमा त्रुटि से बाहर सूचकांक के साथ वापस आता है:

मैं इस कोशिश की।

अंतिम पंक्ति की अद्यतन:

Array2D.init (rows1+rows2) cls (fun i j -> if i < rows1 then arr1.[i,j] else arr2.[i,j]) 

अद्यतन काम कर समाधान:

Array2D.init (rows1+rows2) cls (fun i j -> if i < rows1 then arr1.[i,j] else arr2.[i-rows1,j]) 

धन्यवाद सभी

+1

[यह] (http://stackoverflow.com/a/2367927/969613) – JMK

+0

धन्यवाद मदद कर सकता है।लेकिन क्या यह एक 1 डी सरणी में एकाधिक 1 डी सरणी में शामिल नहीं होता है? मैं एक 2 डी सरणी में एकाधिक 2 डी सरणी में शामिल होना चाहता हूं। लेकिन शायद एक अच्छा प्रारंभिक बिंदु। या मुझे यह नहीं मिल रहा है? – nik

+1

अगर मैं आपको सही ढंग से समझता हूं तो आप केवल 'Array.append' का उपयोग कर सकते हैं। यदि मैं गलत हूं, तो कृपया एक उदाहरण इनपुट और आउटपुट प्रदान करेंगे। – Tobber

उत्तर

6

इस recommendation यहाँ के बाद दो बराबर स्तंभ आकार Array2D तर्क के लिए एक concat समारोह है किसी भी प्रकार के 'a:

let concat (a1: 'a[,]) (a2: 'a[,]) = 
    let a1l1,a1l2,a2l1,a2l2 = (Array2D.length1 a1),(Array2D.length2 a1),(Array2D.length1 a2),(Array2D.length2 a2) 
    if a1l2 <> a2l2 then failwith "arrays have different column sizes" 
    let result = Array2D.zeroCreate (a1l1 + a2l1) a1l2 
    Array2D.blit a1 0 0 result 0 0 a1l1 a1l2 
    Array2D.blit a2 0 0 result a1l1 0 a2l1 a2l2 
    result 

आप Array2D.init क्योंकि Array2D.zeroCreate और Array2D.blit कार्यान्वयन अत्यधिक अनुकूलित कर रहे हैं के आधार पर किसी भी संस्करण की तुलना में प्रयोगात्मक इस जाँच कर सकते हैं, लेकिन यह कई बार बेहतर प्रदर्शन करना होगा।

1

@ जीन ने एक उत्कृष्ट समाधान प्रदान किया है, अंतर्निहित ब्लिट फ़ंक्शन का उपयोग करके यहां बहुत उपयोगी लगता है।

मैं उन यह उपयोगी लग सकते हैं, जो के लिए मॉड्यूल सरणी और Array2D के लिए एक विस्तार के रूप में अपने समारोह के अपने उपयोग पोस्ट करने के लिए करना चाहते हैं:

module Array = 
    let first (arr: 'a array) = arr.[0] 
    let others (arr: 'a array) = arr.[1..] 
    let split arr = first arr, others arr 

module Array2D = 
    let joinByRows (a1: 'a[,]) (a2: 'a[,]) = 
     let a1l1,a1l2,a2l1,a2l2 = (Array2D.length1 a1),(Array2D.length2 a1),(Array2D.length1 a2),(Array2D.length2 a2) 
     if a1l2 <> a2l2 then failwith "arrays have different column sizes" 
     let result = Array2D.zeroCreate (a1l1 + a2l1) a1l2 
     Array2D.blit a1 0 0 result 0 0 a1l1 a1l2 
     Array2D.blit a2 0 0 result a1l1 0 a2l1 a2l2 
     result 

    let joinByCols (a1: 'a[,]) (a2: 'a[,]) = 
     let a1l1,a1l2,a2l1,a2l2 = (Array2D.length1 a1),(Array2D.length2 a1),(Array2D.length1 a2),(Array2D.length2 a2) 
     if a1l1 <> a2l1 then failwith "arrays have different row sizes" 
     let result = Array2D.zeroCreate a1l1 (a1l2 + a2l2) 
     Array2D.blit a1 0 0 result 0 0 a1l1 a1l2 
     Array2D.blit a2 0 0 result 0 a1l2 a2l1 a2l2 
     result 

    // here joiner function must be Array2D.joinByRows or Array2D.joinByCols 
    let joinMany joiner (a: seq<'a[,]>) = 
     let arrays = a |> Array.ofSeq 
     if Array.length arrays = 0 then 
      failwith "no arrays" 
     elif Array.length arrays = 1 then 
      Array.first arrays 
     else 
      let rec doJoin acc arrays = 
       if Array.length arrays = 0 then 
        acc 
       elif Array.length arrays = 1 then 
        joiner acc (Array.first arrays) 
       else 
        let acc = joiner acc (Array.first arrays) 
        doJoin acc (Array.others arrays) 
      doJoin <|| Array.split arrays 
      // or doJoin arrays.[0] arrays.[1..] 
0

@Rustam, इस के लिए धन्यवाद। एक्सेल श्रेणियों के साथ काम करने के लिए मुझे इन कार्यों की आवश्यकता थी। इन कार्यों का उपयोग करने के बाद मुझे सुधार के लिए कुछ जगह मिलीं।

सबसे पहले, यह मानने के बजाय कि ए 1 और ए 2 में शून्य-आधारित इंडेक्स हैं, मैं Array2D.blit फ़ंक्शंस में आपके इंडेक्स के लिए Array2D.base1 और Array2D.base2 का उपयोग करने की अनुशंसा करता हूं। ध्यान दें, यह पता लगाने के लिए मेरे बालों को खींचने में लगभग 4 घंटे लग गए कि यह मेरे कोड में कुछ समस्याएं पैदा कर रहा था। joinByRows समारोह के लिए

अर्थात्:

Array2D.blit a1 (Array2D.base1 a1) (Array2D.base2 a1) result 0 0 a1l1 a1l2 
Array2D.blit a2 (Array2D.base1 a2) (Array2D.base2 a2) result a1l1 0 a2l1 a2l2 

दूसरा, अपने joinMany समारोह Seq.fold का उपयोग करके काफी सरल किया जा सकता:

let joinMany joiner (a: seq<'a[,]>) = 
     Seq.fold joiner (Seq.head a) (Seq.tail a) 

मैं प्रदर्शन की जांच के फ्लॉप लेकिन मैं कल्पना होगा कि बनाया समारोह में अधिक अनुकूलित किया जाएगा।