ما هي أفضل طريقة لاستخراج مصفوفة أحادية البعد من مصفوفة مستطيلة في C#؟

StackOverflow https://stackoverflow.com/questions/232545

  •  04-07-2019
  •  | 
  •  

سؤال

لنفترض أن لدي مصفوفة سلسلة مستطيلة - وليست مصفوفة خشنة

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

ما هي أفضل طريقة لاستخراج مصفوفة أحادية البعد من هذا (إما صف واحد أو عمود واحد)؟يمكنني فعل ذلك باستخدام حلقة for، بالطبع، ولكنني آمل أن يكون لدى .NET طريقة أكثر أناقة مدمجة.

نقاط إضافية لتحويل صفيف السلسلة المستخرجة إلى صفيف كائن.

هل كانت مفيدة؟

المحلول

لمجموعة مستطيلة:

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();

نصائح أخرى

ويمكنك يلقي مجموعة سلسلة لمجموعة الكائن مسلي - الذهاب في الاتجاه الآخر لا يعمل. استخراج الفعلي <م> قد استخدام للحلقة الرغم من ذلك، بقدر ما أستطيع أن أرى: <لأ href = "http://msdn.microsoft.com/en-us/library/system.array. copy.aspx "يختلط =" noreferrer "> Array.Copy يتطلب المصدر والهدف صفوف أن تكون هي نفسها، و <لأ href =" http://msdn.microsoft.com/en-us/library/system. buffer.blockcopy.aspx "يختلط =" noreferrer "> Buffer.BlockCopy فقط يعمل لنوع القيمة المصفوفات. فإنه لا يبدو على الرغم من الغريب ...

ويمكنك استخدام LINQ إلى خارج صف أو عمود في بيان واحد، على الرغم من أنها سوف تكون غير فعالة (كما سوف بناء قائمة داخليا، وبعد ذلك لتحويله إلى مجموعة - إذا كنت تفعل ذلك بنفسك يمكنك preallocate الصفيف إلى الحجم المناسب ونسخ مباشرة).

ونسخ على التوالي (rowNum هو الصف ليتم نسخها):

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();

ولست متأكدا من أن هذا هو حقا أي أفضل / أبسط من حلقة foreach الرغم من ذلك - لا سيما إذا كنت أكتب طريقة ExtractRow وسيلة ExtractColumn وإعادة استخدامها

.

أود فقط التوضيح (في ضوء المثال وما هو مطلوب).

أ مجموعة خشنة عبارة عن مصفوفة من المصفوفات ويتم الإعلان عنها على النحو التالي:

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]" };

مقابل أ مجموعة مستطيلة يتم تعريفها على أنها مصفوفة واحدة تحتوي على أبعاد متعددة:

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

ولهذا السبب أ مجموعة خشنة هو IQueryable/IEnumerable لأنه يمكنك التكرار عليه لتلقي مصفوفة في كل تكرار.حيث أن أ مجموعة مستطيلة يكون لا IQueryable/IEnumerable لأن العناصر تتم معالجتها بالبعد الكامل (0,0 0,1..إلخ) لذلك لن يكون لديك القدرة على استخدام Linq أو أي وظائف محددة مسبقًا تم إنشاؤها لـ Array في هذه الحالة.

على الرغم من أنه يمكنك التكرار على المصفوفة مرة واحدة (وتحقيق ما تريد) مثل هذا:

/// 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;

أتمنى أن يساعدك هذا :)

و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++;
    }
}
يمكن نسخ

والصفوف بسهولة باستخدام 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);

وهذا سوف نسخ الصف الأول في مجموعة واحدة البعد.

وأنا جعلت طريقة ارشادية. أنا لا أعرف عن الأداء.

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) ; 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top