从现有阵列获取子阵列

use*_*637 314 .net c# arrays

我有一个10个元素的数组X. 我想创建一个新的数组,其中包含X中从索引3开始并以索引7结束的所有元素.当然,我可以轻松编写一个循环来为我做这个但我想保持我的代码尽可能干净.C#中有一种方法可以帮我吗?

像(伪代码)的东西:

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)
Run Code Online (Sandbox Code Playgroud)

Array.Copy不符合我的需要.我需要新数组中的项目是克隆.Array.copy只是一个C风格的memcpy等价物,它不是我想要的.

Mar*_*ell 442

您可以将其添加为扩展方法:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}
Run Code Online (Sandbox Code Playgroud)

更新重新克隆(原始问题中不明显).如果你真的想要一个深刻的克隆; 就像是:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}
Run Code Online (Sandbox Code Playgroud)

但这确实需要对象可序列化([Serializable]ISerializable).你可以很容易地替代任何其他串行酌情- XmlSerializer,DataContractSerializer,protobuf网等.

请注意,深度克隆在没有序列化的情况下很棘手; 特别ICloneable是在大多数情况下很难信任.

  • 这很好.特别指出ICloneable不可靠,因为哦,它是永远的. (2认同)

Jon*_*eet 304

您可以Array.Copy(...)在创建新数组后使用它来复制到新数组中,但我认为没有一种方法可以创建新数组复制一系列元素.

如果您使用的是.NET 3.5,则可以使用LINQ:

var newArray = array.Skip(3).Take(5).ToArray();
Run Code Online (Sandbox Code Playgroud)

但效率会低一些.

有关更具体情况的选项,请参阅此答案以获得类似问题.

  • @Ian:LINQ方法引入了两个级别的间接(迭代器),必须显式跳过项目,并且不知道最终数组预先有多大.考虑采用一个两百万元素数组的后半部分:一个简单的"创建目标数组,复制"方法将只复制所需的块而不触及其他元素,并且一气呵成.LINQ方法将遍历数组,直到它到达起始点,然后开始获取值,构建缓冲区(增加缓冲区大小并定期复制).效率低得多. (10认同)

Ale*_*ack 69

你考虑过用过ArraySegment吗?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx

  • 这需要更多的投票.在我自己的exp中,ArraySegment复制也稍微快一些(毕竟我使用数组来获得速度关键的东西). (5认同)
  • @AlexBlack它看起来像[.NET 4.5](http://msdn.microsoft.com/en-us/library/1hsbd92d(v = vs.110).aspx),它实现了`IEnumerable <T>`和各种其他有用的接口. (5认同)
  • @CraigMcQueen - 尝试以下单行方法:`IList <T> newArray =(IList <T>)new ArraySegment <T>(oldArray,beginIndex,endIndex);` (2认同)

zvo*_*kov 33

我看到你想要克隆,而不仅仅是复制引用.在这种情况下,您可以使用.Select将数组成员投影到其克隆.例如,如果您的元素实现了IClonable,您可以执行以下操作:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();
Run Code Online (Sandbox Code Playgroud)


Vol*_*ker 31

以下代码在一行中完成:

// Source array
string[] Source = new string[] { "A", "B", "C", "D" };
// Extracting a slice into another array
string[] Slice = new List<string>(Source).GetRange(2, 2).ToArray();
Run Code Online (Sandbox Code Playgroud)


小智 12

string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();
Run Code Online (Sandbox Code Playgroud)


Ran*_*e42 8

你可以相当容易地做到这一点;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  
Run Code Online (Sandbox Code Playgroud)

  • 哦,嘿,您的权利,我匆匆忙忙地做到了,但是,嘿,也许当您的写作批评成为现实时,建设性的批评对每个人都非常有用。因此在该array.copy之前,您需要执行“ bar = new object [7];” (2认同)

Shu*_*oUk 8

以Marc的答案为基础,但添加了所需的克隆行为

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}
Run Code Online (Sandbox Code Playgroud)

如果使用HåvardStranden的可复制库来实现ICloneable非常像辛勤工作,则需要进行繁重的工作.

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}
Run Code Online (Sandbox Code Playgroud)

请注意,OX.Copyable实现适用于以下任何一个:

但是,要使自动副本起作用,必须保留以下语句之一:

  • 它的类型必须有一个无参数构造函数,或
  • 它必须是可复制的,或者
  • 它必须为其类型注册一个IInstanceProvider.

所以这几乎涵盖了你所拥有的任何情况.如果您正在克隆子图包含数据库连接或文件/流句柄之类的对象,那么您显然会遇到问题,但对于任何通用的深层副本都是如此.

如果你想使用其他一些深层复制方法而不是本文列出了其他几个,所以我建议不要尝试编写自己的.

  • 只是旁注:GitHub上最新版本的Copyable不需要对象具有无参数构造函数.:)请参阅http://github.com/havard/copyable (2认同)

Pra*_*uis 6

在C#8,他们已经推出了新的RangeIndex类型

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }
Run Code Online (Sandbox Code Playgroud)


小智 5

我认为您正在寻找的代码是:

Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)