将对象数组的对象数组转换为对象的二维数组

Ast*_*Dev 11 c# linq arrays

我有一个第三方库返回一个对象数组的对象数组,我可以填充到一个对象[]:

object[] arr = myLib.GetData(...);
Run Code Online (Sandbox Code Playgroud)

结果数组由object []条目组成,因此您可以将返回值视为某种记录集,其中外部数组表示行,而内部数组包含可能未填充某些字段的字段值(锯齿状数组) .要访问各个字段,我必须像:

int i = (int) ((object[])arr[row])[col];//access a field containing an int
Run Code Online (Sandbox Code Playgroud)

现在因为我很懒,我想要访问这样的元素:

int i = (int) arr[row][col];
Run Code Online (Sandbox Code Playgroud)

为此,我使用以下Linq查询:

object[] result = myLib.GetData(...);
object[][] arr = result.Select(o => (object[])o ).ToArray();
Run Code Online (Sandbox Code Playgroud)

我尝试使用简单的强制转换,object[][] arr = (object[][])result;但失败并出现运行时错误.

现在,我的问题:

  • 有更简单的方法吗?我觉得有些漂亮的演员应该做的伎俩?
  • 另外我担心性能,因为我必须重塑大量数据只是为了节省一些时间,所以我想知道这是否真的值得呢​​?

编辑: 谢谢大家的快速回答.
@James:我喜欢你在新课程中结束罪魁祸首的答案,但缺点是我在接受源数组时总是要做Linq包装,而索引器需要row和col值int i = (int) arr[row, col]; (我需要得到一个完整的行也很喜欢object[] row = arr[row];,抱歉没有发布在开头).
@Sergiu Mindras:像James一样,我认为扩展方法有点危险,因为它适用于所有object[]变量.
@Nair:我为我的实现选择了你的答案,因为它不需要使用Linq包装器,我可以int i = (int) arr[row][col];使用object[] row = arr[row];
@quetzalcoatl和@Abe Heidebrecht 使用或整行访问两个单独的字段:感谢提示Cast<>().

Conclusion: I wish I could choose both James' and Nair's answer, but as I stated above, Nair's solution gives me (I think) the best flexibility and performance. I added a function that will 'flatten' the internal array using the above Linq statement because I have other functions that need to be fed with such a structure.

Here is how I (roughly) implemented it (taken from Nair's solution:

public class CustomArray { private object[] data; public CustomArray(object[] arr) { data = arr; }

        //get a row of the data
        public object[] this[int index]
        { get { return (object[]) data[index]; } }

        //get a field from the data
        public object this[int row, int col]
        { get { return ((object[])data[row])[col]; } }

        //get the array as 'real' 2D - Array
        public object[][] Data2D()
        {//this could be cached in case it is accessed more than once
            return data.Select(o => (object[])o ).ToArray()
        }

        static void Main()
        {
            var ca = new CustomArray(new object[] { 
                      new object[] {1,2,3,4,5 },
                      new object[] {1,2,3,4 },
                      new object[] {1,2 } });
            var row = ca[1]; //gets a full row
            int i = (int) ca[2,1]; //gets a field
            int j = (int) ca[2][1]; //gets me the same field
            object[][] arr = ca.Data2D(); //gets the complete array as 2D-array
        }

    }
Run Code Online (Sandbox Code Playgroud)

So - again - thank you all! It always is a real pleasure and enlightenment to use this site.

Jam*_*mes 7

您可以创建一个包装类来隐藏丑陋的转换,例如

public class DataWrapper
{
    private readonly object[][] data;

    public DataWrapper(object[] data)
    {
        this.data = data.Select(o => (object[])o ).ToArray();
    }

    public object this[int row, int col]
    {
        get { return this.data[row][col]; }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

var data = new DataWrapper(myLib.GetData(...));
int i = (int)data[row, col];
Run Code Online (Sandbox Code Playgroud)

还有机会使包装器通用DataWrapper<int>,但是,我不确定您的数据集合是否都是相同的类型,返回object保持它的通用性足以让您决定需要什么样的数据类型.

  • 一个想法:使用您当前的解决方案,每次用户调用`data [1,1]`时,都会计算拆箱.那么,为什么不使用提供的代码OP将`object []`转换为`object [] []`? (2认同)

Nai*_*air 3

几乎没有发布类似的答案来执行类似的操作。仅当您想访问时,这才会有所不同

int i = (int) arr[row][col]; 
Run Code Online (Sandbox Code Playgroud)

为了展示这个想法

   public class CustomArray
        {
            private object[] _arr;
            public CustomArray(object[] arr)
            {
                _arr = arr;
            }

            public object[] this[int index]
            {
                get
                {
                    // This indexer is very simple, and just returns or sets 
                    // the corresponding element from the internal array. 
                    return (object[]) _arr[index];
                }
            }
            static void Main()
            {
                var c = new CustomArray(new object[] { new object[] {1,2,3,4,5 }, new object[] {1,2,3,4 }, new object[] {1,2 } });
                var a =(int) c[1][2]; //here a will be 4 as you asked.
            }

        }
Run Code Online (Sandbox Code Playgroud)