我有一个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
是在大多数情况下很难信任.
Jon*_*eet 304
您可以Array.Copy(...)
在创建新数组后使用它来复制到新数组中,但我认为没有一种方法可以创建新数组并复制一系列元素.
如果您使用的是.NET 3.5,则可以使用LINQ:
var newArray = array.Skip(3).Take(5).ToArray();
Run Code Online (Sandbox Code Playgroud)
但效率会低一些.
有关更具体情况的选项,请参阅此答案以获得类似问题.
Ale*_*ack 69
你考虑过用过ArraySegment
吗?
http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx
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)
你可以相当容易地做到这一点;
object[] foo = new object[10];
object[] bar = new object[7];
Array.Copy(foo, 3, bar, 0, 7);
Run Code Online (Sandbox Code Playgroud)
以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.
所以这几乎涵盖了你所拥有的任何情况.如果您正在克隆子图包含数据库连接或文件/流句柄之类的对象,那么您显然会遇到问题,但对于任何通用的深层副本都是如此.
如果你想使用其他一些深层复制方法而不是本文列出了其他几个,所以我建议不要尝试编写自己的.
在C#8,他们已经推出了新的Range
和Index
类型
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)