The fastest way to grind an array in two parts

I have an array, say:

var arr1 = new [] { 1, 2, 3, 4, 5, 6 };

Now that the size of my array exceeds 5, I want to resize the current array to 3 and create a new array containing the top 3 values, so after this action:

arr1 = new [] { 1, 2, 3 };
newArr = new [] { 4, 5, 6 };

What is the fastest way to do this? I think I’ll have to look into an uncontrollable corner, but I won’t tell you.


Additional Information:

  • Arrays must be scalable without major performance gains.
  • Arrays will only contain Int32
  • The purpose of the array is to group the numbers in my source array without sorting the entire list.

In short: I want to split the following input array:

int[] arr = new int[] { 1, 3, 4, 29, 31, 33, 35, 36, 37 };

at

arr1 =  1, 3, 4
arr2 =  29, 31, 33, 35, 36, 37

but since ideal speed is achieved with an array size of 3, arr2it should be divided into 2 arrays with a uniform size.

Note

, (, , C, , ). , memory move - Win32 API. , :

  • arr1, 3
  • arr2 3
  • , arr1, arr2
+3
5

, - , , Array.Copy. , :)

int[] firstChunk = new int[3];
int[] secondChunk = new int[3];
Array.Copy(arr1, 0, firstChunk, 0, 3);
Array.Copy(arr1, 3, secondChunk, 0, 3);

, , , , :)

, , ArraySegment, "" . , , List<T>, ... .

, - , , .

+6

- ?

static unsafe void DoIt(int* ptr)
{
    Console.WriteLine(ptr[0]);
    Console.WriteLine(ptr[1]);
    Console.WriteLine(ptr[2]);
}

static unsafe void Main()
{
    var bytes = new byte[1024];
    new Random().NextBytes(bytes);

    fixed (byte* p = bytes)
    {
        for (int i = 0; i < bytes.Length; i += sizeof(int))
        {
            DoIt((int*)(p + i));
        }
    }

    Console.ReadKey();
}

( , !) , .

+4

6 , :

var newarr1 = new []{oldarr[0], oldarr[1],oldarr[2]};
var newarr2 = new []{oldarr[3], oldarr[4],oldarr[5]};

.

+2

#, , 5 6, . 3 , . , 5 6 . , 2-3 .

, . - , , ( ). , , .

, . , .


: , ...

public class MyArrayClass
{
    private int[][] _master = new int[10][];
    private int[] _current = new int[3];
    private int _currentCount, _masterCount;

    public void Add(int number)
    {
        _current[_currentCount] = number;
        _currentCount += 1;
        if (_currentCount == _current.Length)
        {
            Array.Copy(_current,0,_master[_masterCount],0,3);
            _currentCount = 0;
            _current = new int[3];
            _masterCount += 1;
            if (_masterCount == _master.Length)
            {
                int[][] newMaster = new int[_master.Length + 10][];
                Array.Copy(_master, 0, newMaster, 0, _master.Length);
                _master = newMaster;
            }
        }
    }

    public int[][] GetMyArray()
    {
        return _master;
    }

    public int[] GetMinorArray(int index)
    {
        return _master[index];
    }

    public int GetItem(int MasterIndex, int MinorIndex)
    {
        return _master[MasterIndex][MinorIndex];
    }
}

. , , , .

0
source

LINQ binding solution:

if(arr1.Length > 5)
{
   var newArr = arr1.Skip(arr1.Length / 2).ToArray();
   arr1 = arr1.Take(arr1.Length / 2).ToArray();
}

LINQ is faster than you think; this will be mainly limited by the ability of the Framework to scroll through IEnumerable (which scrolls through the array pretty quickly). This should be done in approximately linear time and can take any initial size arr1.

-1
source

Source: https://habr.com/ru/post/1766064/


All Articles