2011-09-12 18 views
5

मेरे पास 2 डी सरणी प्रकार बूलियन (महत्वपूर्ण नहीं) गैर-कार्यात्मक शैली में सरणी पर पुनरावृत्ति करना आसान है। इसे एफपी शैली कैसे करें?2 डी स्कैला सरणी पुनरावृत्ति

var matrix = Array.ofDim[Boolean](5, 5) 

पूर्व के लिए, मैं किसी दिए गए स्तंभ के लिए सभी पंक्तियों के माध्यम से पुनरावृति और है कि एक विशेष समारोह से मेल खाएंगे पूर्णांक की एक सूची प्रदान करना चाहते हैं। उदाहरण: कॉलम 3 के लिए, पंक्तियों 1 से 5 के माध्यम से 4, 5 लौटने के लिए पुनरावृत्त करें, यदि सेल (4, 3), (5, 3) पर एक विशिष्ट फ़ंक्शन से मेल खाता है। Thx वी

def getChildren(nodeId: Int) : List[Int] = { 
    info("getChildren("+nodeId+")") 

    var list = List[Int]() 
    val nodeIndex = id2indexMap(nodeId) 

    for (rowIndex <- 0 until matrix.size) { 
     val elem = matrix(rowIndex)(nodeIndex) 
     if (elem) { 
     println("Row Index = " + rowIndex) 
     list = rowIndex :: list 
     } 
    } 

    list 
    } 

उत्तर

4

के बारे में क्या
(1 to 5) filter {i => predicate(matrix(i)(3))} 

जहां predicate अपने समारोह है ज्यादा?

ध्यान दें कि (5,5) सूचकांक प्रारंभ 0 से करने के लिए 4.

अद्यतन जाता है: अपने उदाहरण

def getChildren(nodeId: Int) : List[Int] = { 
    info("getChildren("+nodeId+")") 
    val nodeIndex = id2indexMap(nodeId) 

    val result = (0 until matrix.size).filter(matrix(_)(nodeIndex)).toList 
    result.forEach(println) 
    result 
} 

के आधार पर आप fiter में प्रिंट स्थानांतरित कर सकते हैं अगर आप चाहते हैं भी, और सूची रिवर्स यदि आप इसे बिल्कुल अपने उदाहरण

+0

मुझे लगता है कि प्रारंभिक संरचना 2 डी सरणी है तो आपका सोल एक सरणी वापस कर देगा? – jts

+0

आह, एक और अंतर यह है कि मैं सीधे 2 डी सरणी पर फ़िल्टर करने के बारे में सोच रहा था, लेकिन ऐसा करके, मैं पंक्ति सूचकांक खो रहा हूं: वैल बच्चे = मैट्रिक्स।फ़िल्टर (पंक्ति => पंक्ति (नोडइंडेक्स)) जो 2 1 डी सरणी देता है - लेकिन मुझे नहीं पता कि कौन सा – jts

+0

वास्तव में नहीं, जिस संरचना पर मैं फिटिंग कर रहा हूं वह एक रेंज है, न कि ऐरे (क्योंकि यह इंडेक्स था जो आप चाहते थे उत्पादन)। परिणाम प्रकार एक इंडेक्सडैक [Int] है, और यह एक वेक्टर होता है। बस अगर आप एक सूची चाहते हैं, तो सूची करें, लेकिन वेक्टर आमतौर पर सूची की तुलना में बेहतर संरचना है। –

1
def findIndices[A](aa: Array[Array[A]], pred: A => Boolean): Array[Array[Int]] = 
    aa.map(row => 
    row.zipWithIndex.collect{ 
     case (v,i) if pred(v) => i 
    } 
) 

आप इसे refactor में थोड़ा और अधिक निकाल कर अच्छे होने के लिए कर सकते हैं के रूप में चाहते हैं समारोह है कि केवल एक ही पंक्ति में सूचकांक पाता है:

def findIndices2[A](xs: Array[A], pred: A => Boolean): Array[Int] = 
    xs.zipWithIndex.collect{ 
    case (v,i) if pred(v) => i 
    } 

और फिर

matrix.map(row => findIndices2(row, pred)) 
2

बारे में आप फिल्टर और ज़िप के साथ सहज नहीं हैं, तो आप के साथ छड़ी कर सकते हैं, लेकिन उपयोग-समझ के लिए यह एक अधिक कार्यात्मक रास्ते में:

for { 
    rowIndex <- matrix.indices 
    if matrix(rowIndex)(nodeIndex) 
} yield { 
    println("Row Index = " + rowIndex) 
    rowIndex 
} 

yield के लिए-समझ के परिणामों से एक नया संग्रह बनाता है, तो यह अभिव्यक्ति संग्रह वापस करना चाहते का मूल्यांकन । seq.indices0 until seq.size के समतुल्य एक विधि है। घुंघराले ब्रेसिज़ आप अर्धविराम के बिना कई पंक्तियों अवधि के लिए अनुमति देते हैं, लेकिन आप में लाइन यह कर सकते हैं अगर आप चाहते हैं:

for (rowIndex <- matrix.indices; if matrix(rowIndex)(nodeIndex)) yield rowIndex 

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

for { 
    row <- matrix 
    elem <- row 
} yield f(elem) 

लेकिन अपने यूज-केस थोड़ा असामान्य है कुछ करना चाहते हैं कि यह तत्व है, जो आप सामान्य रूप से साथ नहीं देना चाहिए के सूचकांकों की आवश्यकता है (सरणी सूचकांक का उपयोग कर अनिवार्य रूप से एक त्वरित और एक संख्या के साथ डेटा तत्व जोड़ने के लिए गंदे हैक)। यदि आप स्थिति की धारणा को कैप्चर और उपयोग करना चाहते हैं तो आप Map[Int, Boolean] या case class का उपयोग ऐसे क्षेत्र के साथ कर सकते हैं।

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