2

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?

0

3 Answers 3

3

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")

Sign up to request clarification or add additional context in comments.

1 Comment

Đinh-carabus , I do an optimization test in my answer below, this is easily the most efficient method
1

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

1 Comment

Thanks for the work and performance comparison!
0

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.

4 Comments

to my naive eye, this looks even more complicated and less elegant than the approach in the question. Are you sure it is faster?
This solution creates a temporary array via a for loop and then iterates that array via a for-in loop. From my understanding, this is much slower than the original code I started with - or do you have any explanation on why this is more useful or faster?
@Jere the top lines are just to make it so you don't need to do for let n in [0, 1, 2, 3, 4, 5]. A range generation function.
@Phillipp it's less lengthy code overall than the other answers, and doesn't require any fancy functions. It might be more useful to you. EDIT: but loops, facepalm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.