Philipp
Philipp

Reputation: 11341

Fastest way to set a sequential list of array items to zero

I have a large array of integers, and want to set many sequential values to zero at once. What's the fastest way to do this?

My current solution does not appear very elegant or fast:

const data = getLargeArray();
const startAt = 1750;
const numItems = 4500;

for (let i = 0; i < numItems; i++) {
    data[startAt + i] = 0;
}

Is there a faster way that works without a loop?

Upvotes: 2

Views: 254

Answers (3)

user10873315
user10873315

Reputation:

You don't need libraries, you don't need classes or constructors.

var nums=[0,1,1,2,3,5,8,13,21,34];
function genPythonStyleRange(s, e) {
    var end = [];
    for (let i=s; i<e; i++){
        end.push(i);
    }
    return end;
}
for (let n in genPythonStyleRange(0, 5)){
    nums[n]=0;
}

EDIT

Oh, you don't want a loop? I didn't see that 😔. Considering that, your approach seems all right.

Upvotes: 0

StarshipladDev
StarshipladDev

Reputation: 1145

You can use Array(Size).fill(Value to fill new array with), and then concat a slice of the initial array with that new empty array.

In this way you're not replacing each element in the array, rather the whole section of size X (numItems-startAt) with an Array made up of the replacement value

EDIT: I have included optimization tests for your method, my method and @Đinh-carabus's method (Which is even faster)

//STARSHIPLAD'S ANSWER
const startAt = 1750;
const numItems = 85000;
var data = getLargeArray(numItems);
var newData = data.slice(0,startAt);
newData=newData.concat(Array(numItems-startAt).fill(0));
console.log("Proof it worked: Element 0 is "+newData[0]); //OUTPUT CONSOLE
var randomNumber = Math.floor(Math.random() * numItems);
console.log("Proof it worked: Random element "+randomNumber+" is "+newData[randomNumber]); //OUTPUT CONSOLE
console.log("Proof it worked: Last element is "+newData[numItems-1]); //OUTPUT CONSOLE
//STARSHIPLADS ANSWER
//Testing
runLotsOfTest(startAt,numItems,data);
//Testing


function runLotsOfTest(startAt,numItems,data){
  var test= new Array(3).fill(0);
  var testsToRun =500;
  for(var i=0 ;i<testsToRun;i++){
    var results = runTest(startAt,numItems,data,false);
    var lowestTime =1000;
    var lowestTimeIndex=-1;
    var drawTime = -1;
    for(var f=0; f<results.length;f++){
        if(results[ f]<lowestTime){
          lowestTime=results[f];
          lowestTimeIndex= f;
        }
        if(results[f]==lowestTime){
          drawTime=results[f];
        }
    }
    if(lowestTimeIndex>-1 && drawTime !=lowestTime ){
      test[lowestTimeIndex]=test[lowestTimeIndex]+1;
    }
    if(drawTime == lowestTime){
      for(var f=0; f<results.length;f++){
        if(results[f]==lowestTime){
          test[f]=test[f]+1;
        }
      }
    }
  }
  console.log("Out of "+testsToRun+" tests, ");
  console.log("\t Your method was fastest "+test[0]+" times");
  console.log("\t My method was fastest "+test[1]+" times");
  console.log("\t Dinh's method was fastest "+test[2]+" times");
}



function runTest(startAt,numItems,data,print=false){

  var testTime = new Array(3);
  //OPTIMIZATION TESTS 
  //YOURS
  console.assert(!print,"Testing the speed of each method(Ignore 'assertion Failed'):");
  data = getLargeArray(numItems);
  console.assert(!print,"\t Your way:");
  var date = new Date();
  for(var i=startAt; i< numItems; i++ ){
    data[i]=0;
  }
  var timeTaken= new Date()-date;
  testTime[0]=timeTaken;
  console.assert(!print,"\t \tIt took "+(timeTaken)+"ms");

  //STARSHIPLAD's
  data = getLargeArray(numItems);
  console.assert(!print,"\t My way:");
  date = new Date();
  var newData = data.slice(0,startAt);
  newData=newData.concat(Array(numItems-startAt).fill(0));
  timeTaken= new Date()-date;
  testTime[1]=timeTaken;
  console.assert(!print,"\t \tIt took "+(timeTaken)+"ms");

  //DINH'S
  data = getLargeArray(numItems);
  console.assert(!print,"\t Dinh's way:");
  date = new Date();
  data.fill(0, startAt, startAt + numItems)
  timeTaken= new Date()-date;
  testTime[2]=timeTaken;
  console.assert(!print,"\t \tIt took "+(timeTaken)+"ms");
  return testTime;
}



//IGNORE THIS- SIMPYL FILLS ARRAY
function getLargeArray(numItems){
  var returnArray=[];
  for(var i=0; i<numItems;i++){
    returnArray.push(Math.floor(Math.random() * 500))
  }
  return returnArray;
}

Upvotes: 1

Đinh Carabus
Đinh Carabus

Reputation: 3496

You could use Array.prototype.fill for a more "elegant" solution. It seems to be much faster as well, especially if you want to replace many indices.

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const startAt = 3
const numItems = 5

data.fill(0, startAt, startAt + numItems)

console.log(data)

Performance comparison

const startAt = 1000
const numItems = 100000

const data1 = new Array(1000000).fill(true).map((_, i) => i)
console.time("fill")
data1.fill(0, startAt, startAt + numItems)
console.timeEnd("fill")

const data2 = new Array(1000000).fill(true).map((_, i) => i)
console.time("for loop")
for (var i = 0; i < numItems; i++) {
    data2[startAt + i] = 0
}
console.timeEnd("for loop")

Upvotes: 3

Related Questions