从现有阵列获取子阵列

本文翻译自:Getting a sub-array from an existing array

I have an array X of 10 elements. 我有一个10个元素的数组X. I would like to create a new array containing all the elements from X that begin at index 3 and ends in index 7. Sure I can easily write a loop that will do it for me but I would like to keep my code as clean as possible. 我想创建一个新的数组,其中包含X中从索引3开始到索引7结束的所有元素。当然,我可以轻松编写一个循环,它将为我做,但我想保持我的代码尽可能干净。 Is there a method in C# that can do it for me? C#中有一种方法可以帮我吗?

Something like (pseudo code): 像(伪代码)的东西:

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

Array.Copy doesn't fit my needs . Array.Copy不符合我的需要 I need the items in the new array to be clones. 我需要新数组中的项目是克隆。 Array.copy is just a C-Style memcpy equivalent, it's not what I'm looking for. Array.copy只是一个C风格的memcpy等价物,它不是我想要的。


#1楼

参考:https://stackoom.com/question/3xTv/从现有阵列获取子阵列


#2楼

I see you want to do Cloning, not just copying references. 我看到你想要克隆,而不仅仅是复制引用。 In this case you can use .Select to project array members to their clones. 在这种情况下,您可以使用.Select将数组成员投影到其克隆。 For example, if your elements implemented IClonable you could do something like this: 例如,如果您的元素实现了IClonable您可以执行以下操作:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

Note: This solution requires .NET Framework 3.5. 注意:此解决方案需要.NET Framework 3.5。


#3楼

Building on Marc's answer but adding the desired cloning behaviour 以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;
}

And if implementing ICloneable is too much like hard work a reflective one using Håvard Stranden's Copyable library to do the heavy lifting required. 如果使用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;
}

Note that the OX.Copyable implementation works with any of: 请注意,OX.Copyable实现适用于以下任何一个:

For the automated copy to work, though, one of the following statements must hold for instance: 但是,要使自动副本起作用,必须保留以下语句之一:

  • Its type must have a parameterless constructor, or 它的类型必须有一个无参数构造函数,或
  • It must be a Copyable, or 它必须是可复制的,或者
  • It must have an IInstanceProvider registered for its type. 它必须为其类型注册一个IInstanceProvider。

So this should cover almost any situation you have. 所以这几乎涵盖了你所拥有的任何情况。 If you are cloning objects where the sub graph contains things like db connections or file/stream handles you obviously have issues but that it true for any generalized deep copy. 如果您正在克隆子图包含数据库连接或文件/流句柄之类的对象,那么您显然会遇到问题,但对于任何通用深层副本都是如此。

If you want to use some other deep copy approach instead this article lists several others so I would suggest not trying to write your own. 如果你想使用其他一些深层复制方法而不是本文列出了其他几个,所以我建议不要尝试编写自己的。


#4楼

There's no single method that will do what you want. 没有一种方法可以满足您的需求。 You will need to make a clone method available for the class in your array. 您需要为数组中的类提供克隆方法。 Then, if LINQ is an option: 然后,如果LINQ是一个选项:

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}

#5楼

Cloning elements in an array is not something that can be done in a universal way. 克隆数组中的元素不是可以通用方式完成的。 Do you want deep cloning or a simple copy of all members? 您想要深度克隆还是所有成员的简单副本?

Let's go for the "best effort" approach: cloning objects using the ICloneable interface or binary serialization: 让我们采用“尽力而为”的方法:使用ICloneable接口或二进制序列化克隆对象:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

This is not a perfect solution, because there simply is none that will work for any type of object. 这不是一个完美的解决方案,因为根本没有任何一个适用于任何类型的对象。


#6楼

As far as cloning goes, I don't think serialization calls your constructors. 就克隆而言,我不认为序列化会调用你的构造函数。 This may break class invariants if you're doing interesting things in the ctor's. 如果你在ctor中做有趣的事情,这可能会破坏类不变量。

It seems the safer bet is virtual clone methods calling copy constructors. 似乎更安全的赌注是调用复制构造函数的虚拟克隆方法。

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章