從現有陣列獲取子陣列

本文翻譯自: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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章