如何从多维数组中获取维度(切片)

发布于 2024-10-13 23:33:21 字数 253 浏览 3 评论 0原文

我试图弄清楚如何从多维数组中获取单个维度(为了论证,假设它是二维的),我有一个多维数组:

double[,] d = new double[,] { { 1, 2, 3, 4, 5 }, { 5, 4, 3, 2, 1 } };

如果它是一个锯齿状数组,我只需调用 d[0] ,这会给我一个 {1, 2, 3, 4, 5} 数组,有没有办法可以用二维数组实现相同的效果?

I'm trying to figure out how to get a single dimension from a multidimensional array (for the sake of argument, let's say it's 2D), I have a multidimensional array:

double[,] d = new double[,] { { 1, 2, 3, 4, 5 }, { 5, 4, 3, 2, 1 } };

If it was a jagged array, I would simply call d[0] and that would give me an array of {1, 2, 3, 4, 5}, is there a way I can achieve the same with a 2D array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心舞飞扬 2024-10-20 23:33:22

这应该复制锯齿状数组的 a[r] 功能:

T[] Slice<T>(T[,] a, int r) => Enumerable.Range(0, a.GetUpperBound(1) + 1).Select(i => a[r, i]).ToArray();

This should replicate the a[r] functionality of a jagged array:

T[] Slice<T>(T[,] a, int r) => Enumerable.Range(0, a.GetUpperBound(1) + 1).Select(i => a[r, i]).ToArray();
树深时见影 2024-10-20 23:33:22

已经给出了很好的答案,但我最近对其进行了研究,并将这些方法创建到我的库中:

/// <summary> Iterates the given 2-dimensional array's specified row. A row is all values contained when the left hand index is identical. </summary>
public static IEnumerable<T> IterateRow<T> (T[,] array, int row)
{
    int upperBound = array.GetUpperBound (1);
    for (int i = array.GetLowerBound (1); i <= upperBound; i++)
    {
        yield return array[row, i];
    }
}

/// <summary> Iterates the given 2-dimensional array's specified column. A column is all values contained when the right hand index is identical. </summary>
public static IEnumerable<T> IterateColumn<T> (T[,] array, int column)
{
    int upperBound = array.GetUpperBound (0);
    for (int i = array.GetLowerBound (0); i <= upperBound; i++)
    {
        yield return array[i, column];
    }
}

/// <summary> Returns the given 2-dimensional array's specified row. A row is all values contained when the left hand index is identical. </summary>
public static T[] SliceRow<T> (T[,] array, int row)
{
    int upperBound = array.GetUpperBound (1);
    T[] slice = new T[upperBound + 1];
    for (int i = array.GetLowerBound (1); i <= upperBound; i++)
    {
        slice[i] = array[row, i];
    }
    return slice;
}

/// <summary> Returns the given 2-dimensional array's specified column. A column is all values contained when the right hand index is identical. </summary>
public static T[] SliceColumn<T> (T[,] array, int column)
{
    int upperBound = array.GetUpperBound (0);
    T[] slice = new T[upperBound + 1];
    for (int i = array.GetLowerBound (0); i <= upperBound; i++)
    {
        slice[i] = array[i, column];
    }
    return slice;
}

这些方法略有改进。例如,另一个答案中所写的“i <= array.GetUpperBound(1)”将在每次迭代时运行该方法。还有直接提供一维数组的版本。我更喜欢在迭代方法的方法名称中使用术语“迭代”。我也不再喜欢方法扩展 - 如果它们堆积太多,您可能会在某些时候失去概述。考虑到您无论如何都会(并且应该)需要添加名称空间,它并不会真正加快速度。就我而言,我只使用“int[]firstRow = UtilityFunctions.SliceRow(myArray, 0);”。

Good answers are already given, but I recently worked on it and created these methods into my libraries:

/// <summary> Iterates the given 2-dimensional array's specified row. A row is all values contained when the left hand index is identical. </summary>
public static IEnumerable<T> IterateRow<T> (T[,] array, int row)
{
    int upperBound = array.GetUpperBound (1);
    for (int i = array.GetLowerBound (1); i <= upperBound; i++)
    {
        yield return array[row, i];
    }
}

/// <summary> Iterates the given 2-dimensional array's specified column. A column is all values contained when the right hand index is identical. </summary>
public static IEnumerable<T> IterateColumn<T> (T[,] array, int column)
{
    int upperBound = array.GetUpperBound (0);
    for (int i = array.GetLowerBound (0); i <= upperBound; i++)
    {
        yield return array[i, column];
    }
}

/// <summary> Returns the given 2-dimensional array's specified row. A row is all values contained when the left hand index is identical. </summary>
public static T[] SliceRow<T> (T[,] array, int row)
{
    int upperBound = array.GetUpperBound (1);
    T[] slice = new T[upperBound + 1];
    for (int i = array.GetLowerBound (1); i <= upperBound; i++)
    {
        slice[i] = array[row, i];
    }
    return slice;
}

/// <summary> Returns the given 2-dimensional array's specified column. A column is all values contained when the right hand index is identical. </summary>
public static T[] SliceColumn<T> (T[,] array, int column)
{
    int upperBound = array.GetUpperBound (0);
    T[] slice = new T[upperBound + 1];
    for (int i = array.GetLowerBound (0); i <= upperBound; i++)
    {
        slice[i] = array[i, column];
    }
    return slice;
}

These are slightly refined. For example "i <= array.GetUpperBound(1)" as written in the other answer would run that method with every iteration. Also there are versions that provide the 1-dimensional arrays directly. I prefer to use the term "Iterate" in method names for iterative methods. I am also no fan of method extensions any more - you may lose overview at some point if they stack up too much. And given that you would (and should) need to add the namespace anyway, it doesn't really speed things up much. In my case I just use "int[] firstRow = UtilityFunctions.SliceRow (myArray, 0);".

这个俗人 2024-10-20 23:33:21

不。您当然可以编写一个代表切片的包装类,并在内部有一个索引器 - 但没有任何内置内容。另一种方法是编写一个方法来制作切片的副本并传回向量 - 这取决于您是否想要副本

using System;
static class ArraySliceExt
{
    public static ArraySlice2D<T> Slice<T>(this T[,] arr, int firstDimension)
    {
        return new ArraySlice2D<T>(arr, firstDimension);
    }
}
class ArraySlice2D<T>
{
    private readonly T[,] arr;
    private readonly int firstDimension;
    private readonly int length;
    public int Length { get { return length; } }
    public ArraySlice2D(T[,] arr, int firstDimension)
    {
        this.arr = arr;
        this.firstDimension = firstDimension;
        this.length = arr.GetUpperBound(1) + 1;
    }
    public T this[int index]
    {
        get { return arr[firstDimension, index]; }
        set { arr[firstDimension, index] = value; }
    }
}
public static class Program
{
    static void Main()
    {
        double[,] d = new double[,] { { 1, 2, 3, 4, 5 }, { 5, 4, 3, 2, 1 } };
        var slice = d.Slice(0);
        for (int i = 0; i < slice.Length; i++)
        {
            Console.WriteLine(slice[i]);
        }
    }
}

No. You could of course write a wrapper class that represents a slice, and has an indexer internally - but nothing inbuilt. The other approach would be to write a method that makes a copy of a slice and hands back a vector - it depends whether you want a copy or not.

using System;
static class ArraySliceExt
{
    public static ArraySlice2D<T> Slice<T>(this T[,] arr, int firstDimension)
    {
        return new ArraySlice2D<T>(arr, firstDimension);
    }
}
class ArraySlice2D<T>
{
    private readonly T[,] arr;
    private readonly int firstDimension;
    private readonly int length;
    public int Length { get { return length; } }
    public ArraySlice2D(T[,] arr, int firstDimension)
    {
        this.arr = arr;
        this.firstDimension = firstDimension;
        this.length = arr.GetUpperBound(1) + 1;
    }
    public T this[int index]
    {
        get { return arr[firstDimension, index]; }
        set { arr[firstDimension, index] = value; }
    }
}
public static class Program
{
    static void Main()
    {
        double[,] d = new double[,] { { 1, 2, 3, 4, 5 }, { 5, 4, 3, 2, 1 } };
        var slice = d.Slice(0);
        for (int i = 0; i < slice.Length; i++)
        {
            Console.WriteLine(slice[i]);
        }
    }
}
妄想挽回 2024-10-20 23:33:21

该答案的改进版本

public static IEnumerable<T> SliceRow<T>(this T[,] array, int row)
{
    for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++)
    {
        yield return array[row, i];
    }
}

public static IEnumerable<T> SliceColumn<T>(this T[,] array, int column)
{
    for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
    {
        yield return array[i, column];
    }
}

Improved version of that answer:

public static IEnumerable<T> SliceRow<T>(this T[,] array, int row)
{
    for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++)
    {
        yield return array[row, i];
    }
}

public static IEnumerable<T> SliceColumn<T>(this T[,] array, int column)
{
    for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
    {
        yield return array[i, column];
    }
}
缪败 2024-10-20 23:33:21

矩形阵列不是为此目的而构建的。如果您需要这种类型的功能,您应该切换到锯齿状数组。编写一个将矩形数组转换为锯齿状数组的函数非常简单。

您还可以通过在适当的维度上调用 GetLength(intdimension) 来简单地重建该数组,然后对其进行正确索引以检索每个值。它比转换整个数组更便宜,但最便宜的选择是将其更改为使用锯齿状数组。

Rectangular arrays are not built for this purpose. If you need that type of functionality, you should switch to a jagged array. It is pretty simple to write a function that will convert a rectangular array into a jagged one.

You could also simply rebuild that array by calling GetLength(int dimension) on the appropriate dimension, and then indexing it properly to retrieve each value. It would be cheaper than converting the entire array, but the cheapest option is to change it to use jagged arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文