简体   繁体   English

在C#中从矩形数组中提取一维数组的最佳方法是什么?

[英]What's the best way to extract a one-dimensional array from a rectangular array in C#?

Say I have a rectangular string array - not a jagged array 假设我有一个矩形字符串数组 - 不是锯齿状数组

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

What's the best way to extract a one-dimensional array from this (either a single row or a single column)? 从中提取一维数组(单行还是单列)的最佳方法是什么? I can do this with a for loop, of course, but I'm hoping .NET has a more elegant way built in. 当然,我可以使用for循环执行此操作,但我希望.NET内置更优雅的方式。

Bonus points for converting the extracted string array to an object array. 用于将提取的字符串数组转换为对象数组的加值点。

You can cast a string array to an object array trivially - going the other way doesn't work. 您可以简单地将字符串数组转换为对象数组 - 另一种方式不起作用。 The actual extraction has to use a for loop though, as far as I can see: Array.Copy requires the source and target ranks to be the same, and Buffer.BlockCopy only works for value type arrays. 实际的提取必须使用for循环,据我Array.CopyArray.Copy要求源和目标等级相同,而Buffer.BlockCopy仅适用于值类型数组。 It does seem odd though... 虽然看起来很奇怪......

You can use LINQ to extra a row or column in a single statement, although it will be inefficient (as it'll build up a list internally, then have to convert it to an array - if you do it yourself you can preallocate the array to the right size and copy directly). 您可以在单个语句中使用LINQ来添加行或列,尽管它效率低(因为它会在内部构建列表,然后必须将其转换为数组 - 如果您自己执行,则可以预先分配数组大小合适并直接复制)。

Copying a row ( rowNum is the row to be copied): 复制行( rowNum是要复制的行):

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

Copying a column ( colNum is the column to be copied): 复制列( colNum是要复制的列):

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

I'm not sure that this is really any better/simpler than a foreach loop though - particularly if you write an ExtractRow method and an ExtractColumn method and reuse them. 我不确定这是否比foreach循环更好/更简单 - 特别是如果你编写一个ExtractRow方法和一个ExtractColumn方法ExtractRow用它们。

For a rectangular array: 对于矩形阵列:

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

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

And for a jagged array: 对于锯齿状阵列:

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

I'd just like to clarify (given the example and what's being asked). 我想澄清一下(给出例子以及被问到的内容)。

A jagged array is an array of arrays and is declared like so: 锯齿状数组是一个数组数组,声明如下:

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

Versus a rectangular array being defined as a single array that holds multiple dimensions: 矩形数组相对应 ,定义为包含多个维度的单个数组:

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

Because of this, a jagged array is IQueryable/IEnumerable because you can iterate over it to receive an array at each iteration. 因此, 锯齿状数组是IQueryable / IEnumerable,因为您可以迭代它以在每次迭代时接收数组。 Whereas a rectangular array is not IQueryable/IEnumerable because elements are addressed in full dimension (0,0 0,1..etc) so you won't have the ability to use Linq or any predefined functions created for Array in that case. 矩形数组 不是 IQueryable / IEnumerable,因为元素以全维度(0,0 0,1..etc)进行寻址,因此在这种情况下您将无法使用Linq或为Array创建的任何预定义函数。

Though you can iterate over the array once (and achieve what you want) like this: 虽然您可以迭代一次数组(并实现您想要的),如下所示:

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

Hope this helps :) 希望这可以帮助 :)

LINQ is the answer 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++;
    }
}

Rows can be copied easily using Array.Copy: 可以使用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);

This will copy the first row into the single Dimension array. 这会将第一行复制到单个Dimension数组中。

i made extention method. 我做了扩展方法。 i dont know about the performance . 我不知道性能。

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

usage 用法

// 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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实施一维碰撞检测的最佳方法是什么? - What's the best way to implement one-dimensional collision detection? 如何在c#中创建一维动态数组? - how to create a one-dimensional dynamic array in c#? 从 c# 中二维动态数组的每一行的所有正元素创建一个新的一维数组 - Creating a new one-dimensional array from all positive elements of each row of a two-dimensional dynamic array in c# 有没有一种方法可以将一维数组扩展为具有C#中2D数组的[0]索引中的原始值的2D数组? - Is there a way to expand a one-dimensional Array into a 2D Array with the original values in the [0] index of the 2D Array in C#? 如何在C#中从二维矩形字符数组的一行创建一个字符串? - How do I create a string from one row of a two dimensional rectangular character array in C#? 从string []制作二维数组的最佳方法是什么? - What's the best way to make two dimensional array from string[]? 从其他一维 arrays 初始化一维数组 - Initializing a one-dimensional array from other one-dimensional arrays 如何在c#中的一维数组中找到下一个最小值 - How to find the next minimum value in a one-dimensional array in c# 从asp.net表单中将多个字段提取到准备处理的C#列表或数组中的最佳方法是什么? - What's the best way to extract multiple fields from an asp.net form into a C# list or array ready for processing? 将WPF DataGrid绑定到一维数组 - Bind WPF DataGrid to one-dimensional array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM