Lấy một mảng con từ một mảng hiện có


335

Tôi có một mảng X gồm 10 phần tử. Tôi muốn tạo một mảng mới chứa tất cả các phần tử từ X bắt đầu ở chỉ số 3 và kết thúc ở chỉ mục 7. Chắc chắn tôi có thể dễ dàng viết một vòng lặp sẽ làm điều đó cho tôi nhưng tôi muốn giữ mã của mình sạch nhất có thể . Có một phương pháp trong C # có thể làm điều đó cho tôi không?

Một cái gì đó như (mã giả):

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

Array.Copykhông phù hợp với nhu cầu của tôi . Tôi cần các mục trong mảng mới để được nhân bản. Array.copychỉ là một kiểu C memcpytương đương, nó không phải là thứ tôi đang tìm kiếm.



7
@Kirtan - "dup" đó đặc biệt muốn IEnumerable <T> - khác biệt và có các giải pháp tối ưu khác nhau; IMO
Marc Gravell

Vì vậy, hai dòng mà nó sẽ dùng để khai báo mảng mới và gọi .Copy () không phải là "mã sạch"?
Ed S.

2
@Ed Swangren - không phải nếu bạn cần làm điều đó ở giữa một biểu hiện bị xiềng xích, không ;-p
Marc Gravell

2
Câu trả lời của ShaggyUk có lẽ là câu trả lời đúng: stackoverflow.com/questions/943635/
Đổi

Câu trả lời:


469

Bạn có thể thêm nó dưới dạng một phương thức mở rộng:

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}
}

Cập nhật nhân bản lại (điều không rõ ràng trong câu hỏi ban đầu). Nếu bạn thực sự muốn một bản sao sâu sắc; cái gì đó như:

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);
    }
}

Điều này không đòi hỏi các đối tượng phải được tuần tự hóa ( [Serializable]hoặc ISerializable), mặc dù. Bạn có thể dễ dàng thay thế cho bất kỳ serializer khác như thích hợp - XmlSerializer, DataContractSerializer, protobuf-net vv

Lưu ý rằng bản sao sâu là khó khăn mà không tuần tự hóa; đặc biệt, ICloneablekhó tin tưởng trong hầu hết các trường hợp.


1
(rõ ràng sử dụng chỉ mục kết thúc thay vì độ dài là một thay đổi đơn giản; tôi đã đăng "như hiện tại" vì đó là cách sử dụng "điển hình" hơn)
Marc Gravell

1
Rồi ... khó khăn; nó không làm điều đó .... có lẽ bạn cần sử dụng tuần tự hóa để đạt được điều gì đó tương tự
Marc Gravell

1
xem câu trả lời của tôi cho một số lựa chọn thay thế và một liên kết đến một số triển khai. phần về việc thực hiện nó với một mảng con thực sự khá tầm thường, điều bạn thực sự muốn là bit nhân bản và đó là một câu hỏi phức tạp và hơi mở, phụ thuộc hoàn toàn vào mong đợi của bạn về hành vi 'đúng' .
ShuggyCoUk

2
Cái này đẹp đấy. Và nó đặc biệt tốt khi chỉ ra rằng IClonizable là không đáng tin cậy, bởi vì, nó là bao giờ.
Marcus Griep

1
Cảm ơn vì đã nhấn mạnh các vấn đề với nhân bản sâu trong C #. Thật đáng xấu hổ, vì sao chép sâu là một hoạt động cơ bản .
Dimitri C.

316

Bạn có thể sử dụng Array.Copy(...)để sao chép vào mảng mới sau khi bạn tạo nó, nhưng tôi không nghĩ có một phương pháp tạo ra mảng mới sao chép một loạt các yếu tố.

Nếu bạn đang sử dụng .NET 3.5, bạn có thể sử dụng LINQ:

var newArray = array.Skip(3).Take(5).ToArray();

nhưng điều đó sẽ có phần kém hiệu quả hơn.

Xem câu trả lời này cho một câu hỏi tương tự cho các tùy chọn cho các tình huống cụ thể hơn.


+1 Tôi cũng thích biến thể này. Jon, bạn có thể mở rộng lý do tại sao điều này được coi là kém hiệu quả?
Ian Roke

@Jon: Để khớp với câu hỏi, đó có phải là "Lấy (5)" không? @Ian: Cách tiếp cận Array.Copy không liên quan đến một điều tra viên, và rất có thể sẽ là một bản ghi nhớ thẳng ...
Marc Gravell

@Marc: Vâng thực sự. Quá nhiều câu hỏi lướt qua :)
Jon Skeet

11
@Ian: Cách tiếp cận LINQ giới thiệu hai cấp độ gián tiếp (các vòng lặp), phải bỏ qua rõ ràng các mục và không biết mảng cuối cùng sẽ lớn đến mức nào. Cân nhắc lấy nửa sau của mảng hai triệu phần tử: phương pháp "tạo mảng mục tiêu, sao chép" đơn giản sẽ chỉ sao chép khối yêu cầu mà không cần chạm vào các phần tử khác và trong một lần. Cách tiếp cận LINQ sẽ đi qua mảng cho đến khi đến điểm bắt đầu, sau đó bắt đầu lấy các giá trị, xây dựng bộ đệm (tăng kích thước bộ đệm và sao chép định kỳ). Ít hiệu quả hơn nhiều.
Jon Skeet

nếu 5 là End Indexm, thì câu hỏi đúng là mảng.Skip (3) .Take (5-3 + 1) .ToArray (); I E. mảng.Skip (Start Index) .Take (End Index-Start Index + 1) .ToArray ();
Klaus78

73

Bạn đã cân nhắc sử dụng ArraySegmentchưa?

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


1
Nó có thể làm những gì bạn muốn, nhưng nó không hỗ trợ cú pháp mảng mặc định, cũng không hỗ trợ IEnumerable, vì vậy nó không đặc biệt rõ ràng.
Alex Black

5
Điều này cần upvote nhiều hơn. Trong exp của riêng tôi, sao chép ArraySegment cũng nhanh hơn một chút (sau tất cả tôi sử dụng mảng cho các nội dung quan trọng về tốc độ) ..
nawfal

5
@AlexBlack Giống như .NET 4.5 , nó thực hiện IEnumerable<T>và một loạt các giao diện hữu ích khác.
pswg

1
Làm thế nào bạn sẽ sử dụng ArraySegmentđể trả lời câu hỏi ban đầu?
Craig McQueen

2
@CraigMcQueen - Hãy thử cách tiếp cận một dòng sau:IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
skia.heliou 21/07/2015

36

Tôi thấy bạn muốn thực hiện Nhân bản, không chỉ sao chép tài liệu tham khảo. Trong trường hợp này, bạn có thể sử dụng .Selectđể chiếu các thành viên mảng vào bản sao của chúng. Ví dụ: nếu các yếu tố của bạn được triển khai, IClonablebạn có thể làm một cái gì đó như thế này:

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

Lưu ý: Giải pháp này yêu cầu .NET Framework 3.5.


Điều này là thanh lịch hơn.
smwikipedia

Điều này thật đúng với gì mà tôi đã tìm kiếm. Điều này làm việc cho bất kỳ IEnumerable. Tôi có thể lấy một IEnumerable, IList, IArray, vv ... với fuss tối thiểu, inline nếu tôi cần. Nếu tôi không cần bản sao sâu, tôi chỉ cần xóa Select. Thả Skiphoặc Takecho phép tôi kiểm soát phạm vi. Ngoài ra, tôi có thể kết hợp nó với SkipWhilevà / hoặc TakeWhile.
Mike

33

Đoạn mã sau thực hiện trong một dòng:

// 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();

Dòng Singe và không cần thêm Linq. Đó là cách ưa thích của tôi.
Dimitris

Tuy nhiên, nó vẫn không sao chép nguồn ... nhưng dù sao đó cũng là một cách tiếp cận tốt
IG Pascual

1
Nó nên sao chép nguồn vì ToArray: (1) tạo ra một mảng mới và (2) thực thi Array.Copy. Cuối cùng, Nguồn và Slice là hai đối tượng riêng biệt. Cách tiếp cận là đúng, tuy nhiên, tôi thích Array.Copy: referencesource.microsoft.com/#mscorlib/system/collections/...
Krauss

13

Trong C # 8, họ đã giới thiệu một loại mới RangeIndexloại

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 }

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

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();

8

Dựa trên câu trả lời của Marc nhưng thêm hành vi nhân bản mong muốn

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;
}

Và nếu việc triển khai IClonizable giống như làm việc chăm chỉ thì hãy phản ánh bằng cách sử dụng thư viện Copyable của Håvard Stranden để thực hiện các công việc nặng.

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;
}

Lưu ý rằng việc triển khai OX.Copyable hoạt động với bất kỳ:

Tuy nhiên, để bản sao tự động hoạt động, một trong các câu lệnh sau phải giữ:

  • Kiểu của nó phải có một hàm tạo không tham số, hoặc
  • Nó phải là một bản sao, hoặc
  • Nó phải có IInstanceProvider được đăng ký cho loại của nó.

Vì vậy, điều này sẽ bao gồm hầu hết mọi tình huống bạn có. Nếu bạn đang nhân bản các đối tượng trong đó biểu đồ con chứa những thứ như kết nối db hoặc xử lý tệp / luồng thì rõ ràng bạn có vấn đề nhưng điều đó đúng với mọi bản sao sâu tổng quát.

Nếu bạn muốn sử dụng một số cách tiếp cận sao chép sâu khác thay vì bài viết này liệt kê một số cách khác vì vậy tôi khuyên bạn không nên cố gắng tự viết.


Đầu tiên có lẽ là giải pháp mong muốn, vì anh ta đang yêu cầu nhân bản. Lưu ý rằng với phương thức Sao chép, bạn thậm chí có thể không phải kiểm tra null, vì đây là phương thức mở rộng, nếu chính phương thức đó đã thực hiện điều đó. Đáng để thử.
Dykam

Có, tôi đã lưu ý kiểm tra null nhưng không muốn nhầm lẫn OP trong trường hợp anh ta không đọc nguồn.
ShuggyCoUk

2
Chỉ là một sidenote: Phiên bản mới nhất của Copyable trên GitHub không yêu cầu các đối tượng phải có một hàm tạo không tham số. :) Xem github.com/havard/copyable
Håvard S

8

Bạn có thể làm điều này khá dễ dàng;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  

Không, thanh vẫn sẽ là null. Array.Copy không tạo ra một mảng mới một cách kỳ diệu, đặc biệt là khi thanh không được truyền với ref hoặc out.
Zr40

2
oh ya hey, quyền của bạn, tôi đã làm điều này một cách vội vàng, nhưng này, có lẽ khi bài phê bình bằng văn bản của bạn, bạn nên đưa ra sự điều chỉnh, chủ nghĩa xây dựng mang tính xây dựng rất hữu ích cho mọi người. vì vậy trước mảng đó, bạn thực hiện "bar = new object [7];"
RandomNickName42

4

Tôi nghĩ rằng mã bạn đang tìm kiếm là:

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


Tôi nghĩ rằng tôi đã làm cho một số người bạn tốt ở đây .... cùng một câu trả lời như bạn;) và tôi đã bỏ phiếu rất nhiều !! hả !! Nhưng dù sao, thời điểm tốt thời gian tốt.
RandomNickName42

3

Thay thế cho việc sao chép dữ liệu, bạn có thể tạo một trình bao bọc cho phép bạn truy cập vào một phần của mảng ban đầu như thể đó là bản sao của một phần của mảng. Ưu điểm là bạn không nhận được một bản sao khác của dữ liệu trong bộ nhớ và nhược điểm là một chi phí nhỏ khi truy cập dữ liệu.

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

Sử dụng:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4

@Robert: Không, không phải vậy. Thay vào đó, hãy thử sử dụng ArraySegment và bạn thấy rằng bạn không thể truy cập các mục theo chỉ mục, không lặp lại thông qua các mục.
Guffa

2

Array.ConstrainedCopy sẽ hoạt động.

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)

2
Điều đó chỉ sao chép dữ liệu; Nó sẽ không tạo ra mảng mới, v.v. và nếu mảng là mới, chúng ta có thể sử dụng Array.Copy hiệu quả hơn (không cần kiểm tra / rollback bổ sung).
Marc Gravell

Đúng vậy, nhưng việc tạo một Array mới chỉ là một dòng mã và không yêu cầu phương thức mới nào. Tôi đồng ý rằng Array.Copy cũng sẽ hoạt động.
crauscher

1

Không có phương pháp duy nhất sẽ làm những gì bạn muốn. Bạn sẽ cần phải tạo một phương thức nhân bản có sẵn cho lớp trong mảng của bạn. Sau đó, nếu LINQ là một tùy chọn:

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

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

1

Cách sử dụng Array.ConstrainedCopy :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

Dưới đây là bài viết gốc của tôi. Nó sẽ không làm việc

Bạn có thể sử dụng Array.CopyTo :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

1

Còn cái này thì sao:

public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
{
    T[] retArray = new T[endIndex - startIndex];
    for (int i = startIndex; i < endIndex; i++)
    {
        array[i - startIndex] = array[i].Clone();
    }
    return retArray;

}

Sau đó, bạn cần triển khai giao diện IClonizable trên tất cả các lớp bạn cần sử dụng trên nhưng điều đó nên làm.


1

Tôi không chắc nó thực sự sâu đến đâu, nhưng:

MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()

Đó là một chút chi phí, nhưng nó có thể cắt bỏ một phương pháp không cần thiết.


1

C # 8 đã cung cấp tính năng được gọi là Phạm vi để có được nhóm con từ đầu đến cuối chỉ mục. bạn có thể sử dụng nó như thế này

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

0

Theo như nhân bản, tôi không nghĩ rằng tuần tự hóa gọi các nhà xây dựng của bạn. Điều này có thể phá vỡ bất biến lớp nếu bạn đang làm những điều thú vị trong ctor.

Có vẻ như đặt cược an toàn hơn là các phương thức nhân bản ảo gọi các hàm tạo sao chép.

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}

Cho dù serialization gọi constructor của bạn là tùy thuộc vào serializer cụ thể. Một số làm, một số thì không. Nhưng những người thường không cung cấp hỗ trợ gọi lại để cho phép bạn thực hiện bất kỳ sửa lỗi nào được yêu cầu.
Marc Gravell

Điều này nhấn mạnh một điểm ma sát khác của tuần tự hóa: Bạn phải cung cấp các hàm tạo mặc định.
Hans Malherbe

0

Các yếu tố nhân bản trong một mảng không phải là thứ có thể được thực hiện theo cách phổ quát. Bạn có muốn nhân bản sâu hoặc một bản sao đơn giản của tất cả các thành viên?

Chúng ta hãy thực hiện phương pháp "nỗ lực tốt nhất": nhân bản các đối tượng bằng giao diện IClonizable hoặc tuần tự hóa nhị phân:

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);
    }
  }
}

Đây không phải là một giải pháp hoàn hảo, vì đơn giản là không có giải pháp nào hoạt động cho bất kỳ loại đối tượng nào.


Không phải đó là một cái gì đó giống như kết quả [i-index] = (T) ...?
Donald Byrd

vâng :) Và không chỉ vậy. Ranh giới vòng lặp là sai. Tôi sẽ sửa chữa nó. Cảm ơn!
Philippe Leybaert

0

Bạn có thể tham gia lớp học do Microsoft thực hiện:

internal class Set<TElement>
{
    private int[] _buckets;
    private Slot[] _slots;
    private int _count;
    private int _freeList;
    private readonly IEqualityComparer<TElement> _comparer;

    public Set()
        : this(null)
    {
    }

    public Set(IEqualityComparer<TElement> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TElement>.Default;
        _comparer = comparer;
        _buckets = new int[7];
        _slots = new Slot[7];
        _freeList = -1;
    }

    public bool Add(TElement value)
    {
        return !Find(value, true);
    }

    public bool Contains(TElement value)
    {
        return Find(value, false);
    }

    public bool Remove(TElement value)
    {
        var hashCode = InternalGetHashCode(value);
        var index1 = hashCode % _buckets.Length;
        var index2 = -1;
        for (var index3 = _buckets[index1] - 1; index3 >= 0; index3 = _slots[index3].Next)
        {
            if (_slots[index3].HashCode == hashCode && _comparer.Equals(_slots[index3].Value, value))
            {
                if (index2 < 0)
                    _buckets[index1] = _slots[index3].Next + 1;
                else
                    _slots[index2].Next = _slots[index3].Next;
                _slots[index3].HashCode = -1;
                _slots[index3].Value = default(TElement);
                _slots[index3].Next = _freeList;
                _freeList = index3;
                return true;
            }
            index2 = index3;
        }
        return false;
    }

    private bool Find(TElement value, bool add)
    {
        var hashCode = InternalGetHashCode(value);
        for (var index = _buckets[hashCode % _buckets.Length] - 1; index >= 0; index = _slots[index].Next)
        {
            if (_slots[index].HashCode == hashCode && _comparer.Equals(_slots[index].Value, value))
                return true;
        }
        if (add)
        {
            int index1;
            if (_freeList >= 0)
            {
                index1 = _freeList;
                _freeList = _slots[index1].Next;
            }
            else
            {
                if (_count == _slots.Length)
                    Resize();
                index1 = _count;
                ++_count;
            }
            int index2 = hashCode % _buckets.Length;
            _slots[index1].HashCode = hashCode;
            _slots[index1].Value = value;
            _slots[index1].Next = _buckets[index2] - 1;
            _buckets[index2] = index1 + 1;
        }
        return false;
    }

    private void Resize()
    {
        var length = checked(_count * 2 + 1);
        var numArray = new int[length];
        var slotArray = new Slot[length];
        Array.Copy(_slots, 0, slotArray, 0, _count);
        for (var index1 = 0; index1 < _count; ++index1)
        {
            int index2 = slotArray[index1].HashCode % length;
            slotArray[index1].Next = numArray[index2] - 1;
            numArray[index2] = index1 + 1;
        }
        _buckets = numArray;
        _slots = slotArray;
    }

    internal int InternalGetHashCode(TElement value)
    {
        if (value != null)
            return _comparer.GetHashCode(value) & int.MaxValue;
        return 0;
    }

    internal struct Slot
    {
        internal int HashCode;
        internal TElement Value;
        internal int Next;
    }
}

và sau đó

public static T[] GetSub<T>(this T[] first, T[] second)
    {
        var items = IntersectIteratorWithIndex(first, second);
        if (!items.Any()) return new T[] { };


        var index = items.First().Item2;
        var length = first.Count() - index;
        var subArray = new T[length];
        Array.Copy(first, index, subArray, 0, length);
        return subArray;
    }

    private static IEnumerable<Tuple<T, Int32>> IntersectIteratorWithIndex<T>(IEnumerable<T> first, IEnumerable<T> second)
    {
        var firstList = first.ToList();
        var set = new Set<T>();
        foreach (var i in second)
            set.Add(i);
        foreach (var i in firstList)
        {
            if (set.Remove(i))
                yield return new Tuple<T, Int32>(i, firstList.IndexOf(i));
        }
    }

0

Đây là cách tối ưu, tôi thấy, để làm điều này:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

Hy vọng nó giúp!


0

sử dụng phương pháp gia hạn:

public static T[] Slice<T>(this T[] source, int start, int end)
    {
        // Handles negative ends.
        if (end < 0)
        {
            end = source.Length + end;
        }
        int len = end - start;

        // Return new array.
        T[] res = new T[len];
        for (int i = 0; i < len; i++)
        {
            res[i] = source[i + start];
        }
        return res;
    }

và bạn có thể sử dụng nó

var NewArray = OldArray.Slice(3,7);

0

Mã từ System.Private.CoreLib.dll:

public static T[] GetSubArray<T>(T[] array, Range range)
{
    if (array == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
    }
    (int Offset, int Length) offsetAndLength = range.GetOffsetAndLength(array.Length);
    int item = offsetAndLength.Offset;
    int item2 = offsetAndLength.Length;
    if (default(T) != null || typeof(T[]) == array.GetType())
    {
        if (item2 == 0)
        {
            return Array.Empty<T>();
        }
        T[] array2 = new T[item2];
        Buffer.Memmove(ref Unsafe.As<byte, T>(ref array2.GetRawSzArrayData()), ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), item), (uint)item2);
        return array2;
    }
    T[] array3 = (T[])Array.CreateInstance(array.GetType().GetElementType(), item2);
    Array.Copy(array, item, array3, 0, item2);
    return array3;
}



0

Nó không đáp ứng yêu cầu nhân bản của bạn, nhưng có vẻ đơn giản hơn nhiều câu trả lời:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();

-1
public   static   T[]   SubArray<T>(T[] data, int index, int length)
        {
            List<T> retVal = new List<T>();
            if (data == null || data.Length == 0)
                return retVal.ToArray();
            bool startRead = false;
            int count = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (i == index && !startRead)
                    startRead = true;
                if (startRead)
                {

                    retVal.Add(data[i]);
                    count++;

                    if (count == length)
                        break;
                }
            }
            return retVal.ToArray();
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.