简体   繁体   English

将 c# `Index` 和 `Range` 与锯齿状数组一起使用

[英]Use c# `Index` and `Range` with jagged arrays

I am trying to use Index and Range objects to slice a jagged array.我正在尝试使用IndexRange对象来切片锯齿状数组。 But in the example below I cannot extract columns, only rows.但是在下面的示例中,我无法提取列,只能提取行。

var A =  new float[3][];
A[0] = new float[] { 1.1f, 1.2f, 1.3f };
A[1] = new float[] { 2.1f, 2.2f, 2.3f };
A[2] = new float[] { 3.1f, 3.2f, 3.3f };

// This works as intended to extract rows
var A_row1 = A[0][..];      // { 1.1, 1.2, 1.3 } 
var A_row3 = A[^1][..];     // { 3.1, 3.2, 3.3 } 
var A_row23 = A[1..^0][..]; // { { 2.1, 2.2, 2.3}, { 3.1, 3.2, 3.3 } } 

// This does not work as intended to extract columns
var A_col1 = A[..][0];      // { 1.1, 1.2, 1.3 } ** WRONG
var A_col3 = A[..][^1];     // { 3.1, 3.2, 3.3 } ** WRONG
var A_col23 = A[..][1..^0]; // { { 2.1, 2.2, 2.3}, { 3.1, 3.2, 3.3 } } ** WRONG

var A_sub22 = A[0..2][0..2];
// { { 1.1, 1.2, 1.3 }, { 2.1, 2.2, 2.3 } } ** WRONG
// { { 1.1, 1.2 }, { 2.1, 2.2 } } <= WHAT I AM EXPECTING

Why is it that A[..][0] returns the exact same result as A[0][..] ?为什么A[..][0]返回与A[0][..]完全相同的结果? And why doesn't the last statement contain 2 columns per row, but 3?为什么最后一条语句每行不包含 2 列,而是包含 3 列?

The bigger picture here is that I am building a Matrix object that stores the numeric data in a jagged array of double and I want to implement slicing using Index and Range .这里更大的图景是我正在构建一个Matrix对象,该对象将数字数据存储在一个锯齿状的double数组中,并且我想使用IndexRange实现切片。 I thought I could have it support slicing with the following methods我想我可以让它支持使用以下方法切片

public class Matrix 
{
    readonly double[][] Elements;

    ///<summary>Reference a single element</summary>
    public ref double this[Index row, Index column] 
        => ref Elements[row][column];

    ///<summary>Extract a sub-matrix</summary>
    public double[][] this[Range rows, Range columns]
        => Elements[rows][columns];

    ///<summary>Extract a row sub-vector</summary>
    public double[] this[Index row, Range columns]
        => Elements[row][columns];

    ///<summary>Extract a column sub-vector</summary>
    public double[] this[Range rows, Index column] 
        => Elements[rows][column];
}

But this failed spectacularly in my unit testing.但这在我的单元测试中失败了。 It seems that even if C# supports the syntax, the results are unexpected.看来即使C#支持语法,结果也出乎意料。

Is there a way to implement the functionality I want to have using the existing framework for slicing that C# is trying to implement?有没有办法使用现有的框架来实现我想要的功能来切片 C#试图实现的?


Sorry, I come from a Fortran background where slicing is natural.抱歉,我来自 Fortran 背景,这里的切片很自然。

Also, am I the only one that finds it very confusing that the last element in an array is indexed as [^1] but the range to the last element is [..^0] .另外,我是不是唯一一个觉得数组中的最后一个元素被索引为[^1]但到最后一个元素的范围是[..^0]非常令人困惑的人。 It seems very inconsistent on the part of Microsoft to have ^0 mean different things for Index as it does for Range .对于 Microsoft 而言,让^0IndexRange表示不同的含义似乎非常不一致。

The columns are three different arrays.列是三个不同的数组。 The slicing operators do not work across those different arrays, only within one array.切片运算符不能跨这些不同的数组工作,只能在一个数组内工作。

The only slicing you are doing is on the row array and returns the column arrays according to the operators.您正在做的唯一切片是在行数组上,并根据运算符返回列数组。

A[0][..] returns the first array of A (which is the first column). A[0][..]返回A的第一个数组(即第一列)。 [..] then returns the whole column. [..]然后返回整列。 A[..][0] returns the whole array (which is A again) and then the first entry in A , which is again the first column. A[..][0]返回整个阵列(这是A再次),然后在第一个条目A ,这又是第一列。

This is how I implemented slicing with a jagged array这就是我用锯齿状数组实现切片的方式

public class Matrix 
{
    readonly double[][] Elements;

    /// <summary>
    /// Reference an element of the matrix
    /// </summary>
    /// <param name="row">The row index.</param>
    /// <param name="column">The column index.</param>
    public ref double this[Index row, Index column] 
        => ref Elements[row][column];

    /// <summary>
    /// Extract a sub-matrix.
    /// </summary>
    /// <param name="rows">The range of rows.</param>
    /// <param name="columns">The range of columns.</param>
    public double[][] this[Range rows, Range columns]
    {
        get
        {
            var slice = Elements[rows];
            for (int i = 0; i < slice.Length; i++)
            {
                slice[i] = slice[i][columns];
            }
            return slice;
        }
    }

    /// <summary>
    /// Extract a row sub-vector.
    /// </summary>
    /// <param name="row">The row index.</param>
    /// <param name="columns">The range of columns.</param>
    public double[] this[Index row, Range columns]
    {
        get
        {
            var slice = Elements[row];
            var result = slice[columns];
            return result;
        }
    }

    /// <summary>
    /// Extract a column sub-vector.
    /// </summary>
    /// <param name="rows">The range of rows.</param>
    /// <param name="column">The column index.</param>
    public double[] this[Range rows, Index column]
    {
        get
        {
            var slice = Elements[rows];
            var result = new double[slice.Length];
            for (int i = 0; i < slice.Length; i++)
            {
                result[i] = slice[i][column];
            }
            return result;
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM