'How to convert Java "Arrays.copyOfRange" function to C#?

Working on MergeSort in Java:

public void mergeSort(int[] A)
{
     if (A.length > 1)
     {
         int q = A.length/2;
         int[] leftArray = Arrays.copyOfRange(A, 0, q);
         int[] rightArray = Arrays.copyOfRange(A,q,A.length);
         mergeSort(leftArray);
         mergeSort(rightArray);
         merge(A,leftArray,rightArray);
     }
}

The recursion in the code above works well in Java.

So for curiosity I want to convert function Arrays.copyOfRange from java to c#. Array.copy in C# takes five arguments. Do you know any simpler function in c# do get certain elements of the array starting at position x to y (like java).

In c# I coded the above method like this:

public void mergeSort(int[] A)
{
    if (A.Length > 1)
    {
        int q = A.Length / 2;
        int[] leftArray = new int[q];
        int[] rightArray = new int[A.Length];
        for (int i = 0; i < q; i++)
        {
            leftArray[i] = A[i];
            Console.WriteLine(leftArray[i]);
        }

        for (int i = q; i < A.Length; i++)
        {
            rightArray[i] = A[i];
            Console.WriteLine(rightArray[i]);
        }
        Console.ReadKey();

        mergeSort(leftArray);
        mergeSort(rightArray);
        merge(A, leftArray, rightArray);
    }
}

As you can see I have replaced Arrays.copyOfRange functions in Java with two loops in c# and this works in c# without recursion. However calling mergeSort(leftArray) and mergeSort(rightArray) it prints this in c#:

Process is terminated due to StackOverflowException!!

Any better idea on how to get certain elements in c#?



Solution 1:[1]

The problem is the ported array copy is not doing the same thing.

Given an input of [a,b,c,d,e,f] the Java code is creating two arrays, [a,b,c] and [d,e,f] while the C# port is creating two arrays, [a,b,c] and [0,0,0,d,e,f]. Notably,

  • The new right array is the size of A (new int[A.Length]). This is what causes the StackOverflowException as the termination case is never reached, and;
  • The new right array is only assigned values starting at the q index, which is the half-way index.

Consider this replacement method using Array.Copy - a method with the same signature can be used as a drop in replacement in ported code, as long as what's inside the method has the same effect as the original.

int[] copyOfRange (int[] src, int start, int end) {
    int len = end - start;
    int[] dest = new int[len];
    Array.Copy(src, start, dest, 0, len);
    return dest;
}

Or, a version that does it with a loop but without the issue in the original port. Another reason to use discreet functions - it makes the task easy to see and reason about. Being able to also eliminate duplicate code doesn't hurt.

int[] copyOfRange (int[] src, int start, int end) {
    int len = end - start;
    int[] dest = new int[len];
    // note i is always from 0
    for (int i = 0; i < len; i++)
    {
        dest[i] = src[start + i]; // so 0..n = 0+x..n+x
    }
    return dest;
}

If you're lazy like me, the code could also be trivially written using LINQ.

int[] leftArray = A.Take(q).ToArray();
int[] rightArray = A.Skip(q).ToArray();

Solution 2:[2]

Now in modern C# there is a simple solution for this:

string[] cuttedArray = array[2..6] // from second element to sixth element exclusive

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 UiOpL4504