2008-10-24 19 views
12

कहें कि मेरे पास एक आयताकार स्ट्रिंग सरणी है - एक jagged arrayसी # में एक आयताकार सरणी से एक-आयामी सरणी निकालने का सबसे अच्छा तरीका क्या है?

string[,] strings = new string[8, 3]; 

इस से एक-आयामी सरणी निकालने का सबसे अच्छा तरीका क्या है (या तो एक पंक्ति या एकल कॉलम)? मैं इसे लूप के साथ कर सकता हूं, लेकिन मुझे आशा है कि .NET के पास एक और अधिक सुरुचिपूर्ण तरीका है। Xzx13

निकाले गए स्ट्रिंग सरणी को ऑब्जेक्ट सरणी में परिवर्तित करने के लिए बोनस पॉइंट्स।

उत्तर

7

एक आयताकार सरणी के लिए:

string[,] rectArray = new string[3,3] { 
    {"a", "b", "c"}, 
    {"d", "e", "f"}, 
    {"g", "h", "i"} }; 

var rectResult = rectArray.Cast<object>().ToArray(); 

और एक दांतेदार सरणी के लिए:

string[][] jaggedArray = { 
    new string[] {"a", "b", "c", "d"}, 
    new string[] {"e", "f"}, 
    new string[] {"g", "h", "i"} }; 

var jaggedResult = jaggedArray.SelectMany(s => s).Cast<object>().ToArray(); 
1

LINQ जवाब

static object[] GetColumn(string[][] source, int col) { 
    return source.Iterate().Select(x => source[x.Index][col]).Cast<object>().ToArray(); 
} 
static object[] GetRow(string[][] source, int row) { 
    return source.Skip(row).First().Cast<object>().ToArray(); 
} 
public class Pair<T> { 
    public int Index; 
    public T Value; 
    public Pair(int i, T v) { 
     Index = i; 
     Value = v; 
    } 
} 
static IEnumerable<Pair<T>> Iterate<T>(this IEnumerable<T> source) { 
    int index = 0; 
    foreach (var cur in source) { 
     yield return new Pair<T>(index, cur); 
     index++; 
    } 
} 
+0

मुझे नहीं लगता कि कर रहा है क्या ("या तो एक पंक्ति या एक स्तंभ") के लिए कहा गया है है। –

+0

LINQ आंतरिक रूप से एक लूप का उपयोग नहीं करेगा? – Rohit

+0

जॉन को इंगित करने के लिए धन्यवाद। मैंने जवाब के उस हिस्से से ठीक पहले पढ़ा। – JaredPar

13

आप तुच्छता से एक वस्तु सरणी के लिए एक स्ट्रिंग सरणी डाल सकता है। वास्तविक निष्कर्षण में लूप का उपयोग करने के लिए है, जहां तक ​​मैं देख सकता हूं: Array.Copy के लिए स्रोत और लक्ष्य रैंक समान होना आवश्यक है, और Buffer.BlockCopy केवल मूल्य प्रकार सरणी के लिए काम करता है। हालांकि यह अजीब लगता है ...

आप एकल कथन में पंक्ति या कॉलम के लिए LINQ का उपयोग कर सकते हैं, हालांकि यह अक्षम होगा (क्योंकि यह आंतरिक रूप से एक सूची तैयार करेगा, फिर इसे एक रूप में परिवर्तित करना होगा सरणी - यदि आप इसे स्वयं करते हैं तो आप सरणी को सही आकार में प्रीलोकेट कर सकते हैं और सीधे कॉपी कर सकते हैं)।

object[] row = Enumerable.Range(0, rowLength) 
         .Select(colNum => (object) stringArray[rowNum, colNum]) 
         .ToArray(); 

एक स्तंभ प्रतिलिपि बनाई जा रही (colNum स्तंभ कॉपी किया जा रहा है):

object[] column = Enumerable.Range(0, columnLength) 
          .Select(rowNum => (object) stringArray[rowNum, colNum]) 
          .ToArray(); 

मुझे लगता है कि यकीन नहीं है

एक पंक्ति प्रतिलिपि बनाई जा रही (rowNum पंक्ति कॉपी किया जा रहा है) यह वास्तव में फ़ोरैच लूप की तुलना में कोई बेहतर/सरल है - खासकर अगर आप ExtractRow विधि और ExtractColumn विधि लिखते हैं और उनका पुन: उपयोग करते हैं।

+0

बस यह सुनिश्चित कर लें कि मैं पहिया को पुनर्निर्मित नहीं कर रहा हूं। यह विशेष कार्य निश्चित रूप से प्रकृति में नहीं होता है जो अक्सर अंतर्निहित फ़ंक्शन को वारंट करने के लिए पर्याप्त होता है। – MusiGenesis

+1

मुझे नहीं पता - मुझे लगता है कि फ्रेमवर्क का समर्थन करने वाली अधिक अस्पष्ट चीजें हैं। मैं अभी भी थोड़ा हैरान हूं कि एक पंक्ति प्रति नहीं है (जैसा कि यह विचित्र होना चाहिए)। –

4

मैं सिर्फ स्पष्टीकरण देना चाहता हूं (उदाहरण दिया गया है और क्या पूछा जा रहा है)।

एक दांतेदार सरणी सरणियों की एक सरणी है और इस तरह तो घोषित किया जाता है:

string[,] data = new string[3,3]; 
data[0,0] = "0,0"; 
data[0,1] = "0,1"; 
data[0,2] = "0,2"; 
...etc 
:

string[][] data = new string[3][]; 
data[0] = new string[] { "0,[0]", "0,[1]", "0,[2]" }; 
data[1] = new string[] { "1,[0]", "1,[1]", "1,[2]" ]; 
data[2] = new string[] { "2,[0]", "1,[1]", "1,[2]" }; 

एक आयताकार सरणी बनाम एक सारिणी कि कई आयामों धारण के रूप में परिभाषित किया जा रहा

इस वजह से, jagged array IQueryable/IEnumerab है ले क्योंकि आप प्रत्येक पुनरावृत्ति पर एक सरणी प्राप्त करने के लिए इसे पुन: सक्रिय कर सकते हैं। एक आयताकार सरणी जबकिहै नहीं IQueryable/IEnumerable क्योंकि तत्वों पूर्ण आयाम (0,0 0,1..etc) में संबोधित कर रहे हैं ताकि आप Linq या के लिए बनाए गए किसी भी पूर्वनिर्धारित कार्यों का उपयोग करने की क्षमता नहीं होगा उस मामले में ऐरे।

आप सरणी एक बार से अधिक पुनरावृति कर सकते हैं हालांकि (और प्राप्त आप क्या चाहते हैं) इस तरह:

/// INPUT: rowIndex, OUTPUT: An object[] of data for that row 
int colLength = stringArray.GetLength(1); 
object[] rowData = new object[colLength]; 
for (int col = 0; col < colLength; col++) { 
    rowData[col] = stringArray[rowIndex, col] as object; 
} 
return rowData; 

/// INPUT: colIndex, OUTPUT: An object[] of data for that column 
int rowLength = stringArray.GetLength(0); 
object[] colData = new object[rowLength]; 
for (int row = 0; r < rowLength; row++) { 
    colData[row] = stringArray[row, colIndex] as object; 
} 
return colData; 

आशा इस मदद करता है :)

+0

यह सच नहीं है। जैसा कि बताया गया है [यहां] (http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx), ऐरे प्रकार बेस प्रकार [एरे] से प्राप्त होते हैं (http://msdn.microsoft.com/en -us/लाइब्रेरी/system.array.aspx) जो IENumerable लागू करता है। तो आप कुछ लिंक विधियों का उपयोग कर सकते हैं, बस उन सभी को नहीं। उदाहरण के लिए () कास्ट ठीक काम करता है। –

1

पंक्तियाँ Array.Copy का उपयोग कर आसानी से कॉपी किया जा सकता:

 int[][] arDouble = new int[2][]; 
     arDouble[0] = new int[2]; 
     arDouble[1] = new int[2]; 
     arDouble[0][0] = 1; 
     arDouble[0][1] = 2; 
     arDouble[1][0] = 3; 
     arDouble[1][1] = 4; 

     int[] arSingle = new int[arDouble[0].Length]; 

     Array.Copy(arDouble[0], arSingle, arDouble[0].Length); 

यह पहली पंक्ति को एकल आयाम सरणी में कॉपी करेगा।

+0

यह दो dimesional सरणी के लिए काम नहीं करता है, जैसा उपरोक्त के उत्तर में देखा गया है। –

+0

मुझे लगता है कि शब्दावली, "आयताकार सरणी" है "दो आयामी" नहीं –

+0

मैं सवाल "दो आयामी" के बजाय का उपयोग करने के लिए "आयताकार" का संपादन किया। – MusiGenesis

0

मैं विस्तार विधि बनाया है। मैं प्रदर्शन के बारे में नहीं जानता।

public static class ExtensionMethods 
{ 
    public static string[] get1Dim(this string[,] RectArr, int _1DimIndex , int _2DimIndex ) 
    { 
     string[] temp = new string[RectArr.GetLength(1)]; 

     if (_2DimIndex == -1) 
     { 
      for (int i = 0; i < RectArr.GetLength(1); i++) 
      { temp[i] = RectArr[_1DimIndex, i]; } 
     } 
     else 
     { 
      for (int i = 0; i < RectArr.GetLength(0); i++) 
      { temp[i] = RectArr[ i , _2DimIndex]; } 
     } 

     return temp; 
     } 
} 

उपयोग

// we now have this funtionaliy RectArray[1, * ] 
//          -1 means ALL  
string[] _1stRow = RectArray.get1Dim(0, -1) ;  
string[] _2ndRow = RectArray.get1Dim(1, -1) ; 

string[] _1stCol = RectArray.get1Dim(-1, 0) ;  
string[] _2ndCol = RectArray.get1Dim(-1, 1) ; 
संबंधित मुद्दे

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