2011-09-06 14 views
8

मान लें कि हम एक दांतेदार सरणीसरणी संचालन

int[][] a = { new[] { 1, 2, 3, 4 }, new[] { 5, 6, 7, 8 }, new[] { 9, 10, 11, 12 } }; 

दूसरी पंक्ति और दूसरे स्तंभ का योग की राशि प्राप्त करने के लिए है, यह दोनों कोड लाइनों क्रमशः लिखा जा सकता है:

int rowSum = a[1].Sum(); 
int colSum = a.Select(row => row[1]).Sum(); 

लेकिन अगर हम 2-आयामी सरणी की परिभाषा है

int[,] a = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 

ऊपर बताए गए कोड काम नहीं करेगा compiller त्रुटियों के कारण:

Error 1 Wrong number of indices inside []; expected 2 
Error 2 'int[*,*]' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'int[*,*]' could be found (are you missing a using directive or an assembly reference?) 

तो, सवाल: n आयामी सरणियों के साथ LINQ तरीकों का उपयोग कैसे करें, लेकिन नहीं दांतेदार वाले? और जहां आयताकार सरणी को जंजीर में बदलने की विधि है?

पीएस मैंने दस्तावेज में जवाब खोजने की कोशिश की, लेकिन बिना परिणाम के।

+0

बहु आयामी सरणी नहीं वास्तव में (बड़े पैमाने पर) सी # में :-( – xanatos

उत्तर

15

LINQ to ObjectsIEnumerable<T> Interface पर आधारित है, यानी मानों का एक आयामी अनुक्रम। इसका मतलब है कि यह गैर-आयामी डेटा संरचनाओं जैसे गैर-जाग्रत सरणी के साथ अच्छी तरह से मिश्रण नहीं करता है, हालांकि यह संभव है।

आप पूर्णांकों का एक आयामी अनुक्रम उत्पन्न कर सकते हैं कि एन-आयामी सरणी में सूचकांक:

int rowSum = Enumerable.Range(0, a.GetLength(1)).Sum(i => a[1, i]); 

int colSum = Enumerable.Range(0, a.GetLength(0)).Sum(i => a[i, 1]); 
+1

+1 समर्थित हैं क्या कर रहा है: दिलचस्प दृष्टिकोण –

3

अपने प्रश्न के बारे में "कैसे n आयामी सरणियों के साथ LINQ तरीकों का उपयोग करने के लिए":

आप अधिकांश LINQ विधियों का उपयोग एक आयामी सरणी के साथ नहीं कर सकता है, क्योंकि ऐसा सरणी केवल IEnumerable लागू करता है लेकिन IEnumerable<T> नहीं है और अधिकांश LINQ एक्सटेंशन विधियां IEnumerable<T> के लिए एक्सटेंशन विधियां हैं।

अन्य प्रश्न के बारे में: डीटीबी का जवाब देखें।

3

DTB के समाधान के लिए जोड़ने के लिए, सरणी के सभी आइटम्स से अधिक पुनरावृत्ति की एक अधिक सामान्य तरीका होगा:

int[,] b = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 

var flattenedArray = Enumerable.Range(0, b.GetLength(0)) 
        .SelectMany(i => Enumerable.Range(0, b.GetLength(1)) 
         .Select(j => new { Row = i, Col = j })); 

और अब:

var rowSum2 = flattenedArray.Where(t => t.Row == 1).Sum(t => b[t.Row, t.Col]); 
var colSum2 = flattenedArray.Where(t => t.Col == 1).Sum(t => b[t.Row, t.Col]); 

बेशक इस के रूप में अति बेकार है हम उन वस्तुओं के लिए भी समन्वय tuples बना रहे हैं कि हम Where के साथ फ़िल्टरिंग समाप्त हो जाएगा, लेकिन अगर आपको नहीं पता कि चयन मानदंड पहले से क्या होगा, तो यह जाने का तरीका है (या नहीं - यह एक व्यायाम की तरह लगता है कुछ ऐसा जो आप अभ्यास में करना चाहते हैं)।

मैं यह भी कल्पना कर सकता हूं कि इसे रिकर्सिव लैम्ब्डा और Tuple जैसे किसी भी रैंक (केवल 2 डी) के सरणी के लिए कैसे बढ़ाया जा सकता है, लेकिन यह मासोचिज्म क्षेत्र में पार हो जाता है।

1

2 डी सरणी में कोई पंक्ति या स्तंभ पर पुनरावृत्ति करने के तरीके में कोई भी अंतर्निहित नहीं है। यद्यपि अपनी खुद की विधि बनाना मुश्किल नहीं है। इस वर्ग को कार्यान्वयन के लिए देखें जो पंक्ति और स्तंभ के लिए एक संख्यात्मक हो जाता है।

public static class LINQTo2DArray 
{ 
    public static IEnumerable<T> Row<T>(this T[,] Array, int Row) 
    { 
     for (int i = 0; i < Array.GetLength(1); i++) 
     { 
      yield return Array[Row, i]; 
     } 
    } 
    public static IEnumerable<T> Column<T>(this T[,] Array, int Column) 
    { 
     for (int i = 0; i < Array.GetLength(0); i++) 
     { 
      yield return Array[i, Column]; 
     } 
    } 
} 

तुम भी सरणी a.Cast<int>() का उपयोग कर समतल कर सकते हैं, लेकिन आप तो ढीला होगा के बारे में कॉलम/पंक्तियों

-1

सरल LINQ केवल दृष्टिकोण मैं एक पर पंक्ति और स्तंभ के संचालन के इन प्रकार करने के लिए देख सकते हैं सभी जानकारी दो आयामी सरणी निम्नलिखित लुकअप परिभाषित करने के लिए है:

var firstColumnSum = cols[0].Sum(); 
:

var cols = a 
    .OfType<int>() 
    .Select((x, n) => new { x, n, }) 
    .ToLookup(xn => xn.n % a.GetLength(1), xn => xn.x); 

var rows = a 
    .OfType<int>() 
    .Select((x, n) => new { x, n, }) 
    .ToLookup(xn => xn.n/a.GetLength(1), xn => xn.x); 

अब आप बस यह कर सकते हैं

एन-आयामी के लिए, यह बहुत दर्दनाक हो जाता है ... क्षमा करें।

0

एक आसान तरीका की तरह नीचे

var t = new List<Tuple<int, int>>(); 
int[][] a = t.Select(x => new int[]{ x.Item1, x.Item2}).ToArray(); 
संबंधित मुद्दे