Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace a given value in array with values from second array in C#

I have an array of ints which has a number of negative values in:

var arrayExisting = new int[]{1,2,-1,3,5,-1,0,0,-1};

And another array with a corresponding set of values I want to insert into the first array:

var replacements = new int[]{7,6,5};

Is there a truly efficient way of doing this?

What I have currently is:

var newArray = arrayExisting.Select(val =>
        {
            if (val != -1) return val;
            var ret = replacements[i];
            i++;
            return ret;
        }).ToArray();

It's fairly quick. The arrays in question are only about 15 integers in length, and this might go up, but unlikely to exceed 100. The problem is that I have to do this over a quarter of a million times for my moderate test system, and the realistic system I am considering will involve about 10e10 iterations of this code!

like image 611
MikeW Avatar asked Sep 25 '22 16:09

MikeW


1 Answers

I would use a for loop and replace values in your original array in-place.

int replacementIndex = 0;
for (var i = 0; i < arrayExisting.Length; i++) {
    if (arrayExisting[i] < 0) {
        arrayExisting[i] = replacements[replacementIndex++];
    }
}

This way you avoid the overhead creating a new array. If you need to create a new array you can create a new int[arrayExisting.Length]

Running a quick benchmark it seems that the for loop is ~4x faster, even in the worst case where you have to replace every single time and you construct a new array to hold the replacements.

Select: 12672
For: 3386

Here's the benchmark if you're intrested.

var loops = 1000000;
            var arrayExisting = Enumerable.Repeat(-1, 1000).ToArray();
            var replacements = Enumerable.Repeat(1, 1000).ToArray();

            var selectTimer = Stopwatch.StartNew();
            for (var j = 0; j < loops; j++)
            {
                var i = 0;
                var newArray = arrayExisting.Select(val =>
                {
                    if (val != -1) return val;
                    var ret = replacements[i];
                    i++;
                    return ret;
                }).ToArray();
            }
            selectTimer.Stop();

            var forTimer = Stopwatch.StartNew();
            for (var j = 0; j < loops; j++)
            {
                var replaced = new int[arrayExisting.Length];
                int replacementIndex = 0;
                for (var i = 0; i < arrayExisting.Length; i++)
                {
                    if (arrayExisting[i] < 0)
                    {
                        replaced[i] = replacements[replacementIndex++];
                    }
                    else
                    {
                        replaced[i] = arrayExisting[i];
                    }
                }
            }
            forTimer.Stop();

            Console.WriteLine("Select: " + selectTimer.ElapsedMilliseconds);
            Console.WriteLine("For: " + forTimer.ElapsedMilliseconds);
like image 126
Joey Ciechanowicz Avatar answered Sep 28 '22 04:09

Joey Ciechanowicz