Reputation: 11341
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
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;
}
Oh, you don't want a loop? I didn't see that 😔. Considering that, your approach seems all right.
Upvotes: 0
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
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