all possible combinations in javascript - why pop()? - javascript

I'm trying to understand this function that I came across online that returns all possible combinations of a string -- why exactly is the pop() call needed with nextLetter.pop? I tried debugging this in the console but it's not clear what the pop does exactly.
result with nextLetter.pop() ---> [ 'bac', 'bca', 'cba', 'cab', 'acb', 'abc' ]
result without nextLetter.pop() --> [ 'bac',
'bacca',
'baccacba',
'baccacbaab',
'baccacbaabacb',
'baccacbaabacbbc' ]
function stringPermutations(str) {
var permutations = [];
var nextLetter = [];
var chars = str.split('');
permutateInner(chars);
function permutateInner(chars) {
if (chars.length === 0) {
permutations.push(nextLetter.join(''));
}
for (var i = 0; i < chars.length; i++) {
chars.push(chars.shift());
nextLetter.push(chars[0]);
permutateInner(chars.slice(1));
//what is this doing?
nextLetter.pop();
}
}
return permutations;
}
console.log(stringPermutations('abc'));

permutateInner(chars.slice(1)); does recursion on array subset [1..n]. It is included to have permutation also for each subarray of current array.
e.g. when current first letter is b, recursion includes permutations ac and ca. when current first letter is a, recursion includes permutations cb and bc.
It is crucial to have it there, otherwise you would get only result [ 'abc', 'bca', 'cba' ]

Starting at the top, it's clear that nextLetter is an Array -- so the first place I'd look would be the docs on MDN.
As the documentation says, the .pop() method removes the last element from the Array and returns it -- in your sample code the return value isn't being used, so clearly what's useful is the side effect of removing the last element.

Related

for loop skipping one item in array in javascript

I am trying to make a function that removes strings from an array if they include a character in a certain other list
Here is the code:
var possible = ["salutations", "goodbye", "thanks", "welcome"];
var incorrect = ["o"];
console.log(possible);
function narrowdown(possible, incorrect)
{
var templist = possible;
for (i in possible)
{
console.log(i + " " + possible[i]);
var array1 = possible[i].split("");
var common = array1.filter(value => incorrect.includes(value));
console.log(common)
if (common.length)
{
templist.splice(i, 1);
}
}
possible = templist;
}
narrowdown(possible, incorrect);
console.log(possible);
Here I am trying to remove all the words that include the letter o. I created a temporary array in the function because it has happened to me before that a for loop skips items altogether.
The code first logs the index of the item in the list and then the item itself.
Then it turns the word into an array and checks for overlap between it and the "incorrect" array. It does that correctly and logs the overlapping characters.
The issue seems to be that it skips over the "goodbye" item for some reason. It doesn't even process it.
Here is the output I am getting:
[ 'salutations', 'goodbye', 'thanks', 'welcome' ]
0 salutations
[ 'o' ]
1 thanks
[]
2 welcome
[ 'o' ]
[ 'goodbye', 'thanks' ]
First of all, for (i in possible) is a bad way of looping through an array since it retrieves the keys before the loop begins and it never updates that list of keys. Also, if someone assigns an attribute to the array, like possible.foo = 17, then your loop will also go through that. The issue you're having is that when you splice the array, everything else is shifted one to the left, changing their indices to be one less, so your new index actually skips over the next element. The fix is to use a conventional for loop and decrement i after splicing:
for (let i = 0; i < possible.length; i ++) {
// more code...
if (common.length) {
templist.splice(i, 1);
i --;
}
}
The problem is that the array is re-indexed when you splice. One solution is to iterate in reverse:
var possible = ["salutations", "goodbye", "thanks", "welcome"];
var incorrect = ["o"];
console.log(possible);
function narrowdown(possible, incorrect)
{
var templist = possible;
var i = possible.length;
while (i--)
{
console.log(i + " " + possible[i]);
var array1 = possible[i].split("");
var common = array1.filter(value => incorrect.includes(value));
console.log(common)
if (common.length)
{
templist.splice(i, 1);
}
}
possible = templist;
}
narrowdown(possible, incorrect);
console.log(possible);
The issue comes from the line tempList = possible which is an assignment by reference, meaning that when you do the splice operation you do it on both arrays at the same time.
Generally it is considered bad form to manipulate data like that anyway, you should have narrowDown return a value that you re-assign to possible instead of filtering them in place. If you do that you can also leverage some of the newer array methods:
var possible = ["salutations", "goodbye", "thanks", "welcome"];
var incorrect = ["o"];
function narrowdown(possible, incorrect)
{
return possible.filter(item => !incorrect.some(test => item.includes(test)))
}
possible = narrowdown(possible, incorrect);
console.log(possible);
using the .some will also exit early as soon as there is a match, instead of looping over all incorrect values and the entire string, boosting performance slightly
If you're looking for a less "imperative" version of this function, you can make use of Array.filter(), Array.some(), and String.includes() to make a one-liner function that does the trick (for formatting purposes, I split it in the multiple lines in the snippet below).
const possible = ['salutations', 'goodbye', 'thanks', 'welcome'];
function narrowDown(possible, incorrect) {
return possible.filter((value) => (
!incorrect.some((exclude) => (value.includes(exclude)))
));
}
console.log('["o"]', JSON.stringify(narrowDown(possible, ['o'])));
console.log('["a"]', JSON.stringify(narrowDown(possible, ['a'])));
console.log('["a", "o"]', JSON.stringify(narrowDown(possible, ['a', 'o'])));

Find word in string using RegEx javascript

How can I make a search function using regEx?
I have some code but can't post it at the moment due to my computer being very broken and annoying, I will try again tomorrow!
This is not really what would be called combinations, but permutations.
The idea is to use recursion for getting the result for a shorter array, i.e. the one that lacks the first element.
Then take all permutations you get back from the recursive call, and insert the left-out value in each possible index.
When input has duplicates, then you need to stop inserting the left-out value as soon as you find that same value preceding the insertion spot.
Here is how that looks:
function scramble(array) {
if (array.length == 0) {
return [[]];
}
let results = [];
// solve the problem for a shorter array (first value excluded), and iterate:
for (let perm of scramble(array.slice(1))) {
// add the missing element in each possible position:
for (let i = 0; i < array.length; i++) {
// next IF is only needed when input has duplicates, and
// output should not repeat same array:
if (i && array[0] === perm[i-1]) break;
results.push(perm.slice(0, i).concat(array[0], perm.slice(i)));
}
}
return results;
}
let array = ["I", "am", "coding", "am"];
console.log(scramble(array));
Without the inner if, an input with duplicate values will produce duplicate arrays. If this is not desired, then the if is needed.
You could iterate and get a flat array of the mapping of the value with the result of the nested calls.
function permutation(array) {
return array.length === 1
? [array]
: array.flatMap((v, i) => permutation([
...array.slice(0, i),
...array.slice(i + 1)
]).map(a => [v, ...a]));
}
permutation(["I", "am", "coding"]).map(a => console.log(...a));

How to remove a JavaScript component (object) [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
Is there a way to empty an array and if so possibly with .remove()?
For instance,
A = [1,2,3,4];
How can I empty that?
Ways to clear an existing array A:
Method 1
(this was my original answer to the question)
A = [];
This code will set the variable A to a new empty array. This is perfect if you don't have references to the original array A anywhere else because this actually creates a brand new (empty) array. You should be careful with this method because if you have referenced this array from another variable or property, the original array will remain unchanged. Only use this if you only reference the array by its original variable A.
This is also the fastest solution.
This code sample shows the issue you can encounter when using this method:
var arr1 = ['a','b','c','d','e','f'];
var arr2 = arr1; // Reference arr1 by another variable
arr1 = [];
console.log(arr2); // Output ['a','b','c','d','e','f']
Method 2 (as suggested by Matthew Crumley)
A.length = 0
This will clear the existing array by setting its length to 0. It also works when using "strict mode" in ECMAScript 5 because the length property of an array is a read/write property.
Method 3 (as suggested by Anthony)
A.splice(0,A.length)
Using .splice() will work perfectly, but since the .splice() function will return an array with all the removed items, it will actually return a copy of the original array. Benchmarks suggest that this has no effect on performance whatsoever.
Method 4 (as suggested by tanguy_k)
while(A.length > 0) {
A.pop();
}
This solution is not very succinct, and it is also the slowest solution, contrary to earlier benchmarks referenced in the original answer.
Performance
Of all the methods of clearing an existing array, methods 2 and 3 are very similar in performance and are a lot faster than method 4. See this benchmark.
As pointed out by Diadistis in their answer below, the original benchmarks that were used to determine the performance of the four methods described above were flawed. The original benchmark reused the cleared array so the second iteration was clearing an array that was already empty.
The following benchmark fixes this flaw: http://jsben.ch/#/hyj65. It clearly shows that methods #2 (length property) and #3 (splice) are the fastest (not counting method #1 which doesn't change the original array).
This has been a hot topic and the cause of a lot of controversy. There are actually many correct answers and because this answer has been marked as the accepted answer for a very long time, I will include all of the methods here.
If you need to keep the original array because you have other references to it that should be updated too, you can clear it without creating a new array by setting its length to zero:
A.length = 0;
Here the fastest working implementation while keeping the same array ("mutable"):
function clearArray(array) {
while (array.length > 0) {
array.pop();
}
}
FYI it cannot be simplified to while (array.pop()): the tests will fail.
FYI Map and Set define clear(), it would have seem logical to have clear() for Array too.
TypeScript version:
function clearArray<T>(array: T[]) {
while (array.length > 0) {
array.pop();
}
}
The corresponding tests:
describe('clearArray()', () => {
test('clear regular array', () => {
const array = [1, 2, 3, 4, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
test('clear array that contains undefined and null', () => {
const array = [1, undefined, 3, null, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
});
Here the updated jsPerf: http://jsperf.com/array-destroy/32 http://jsperf.com/array-destroy/152
jsPerf offline. Similar benchmark: https://jsben.ch/hyj65
A more cross-browser friendly and more optimal solution will be to use the splice method to empty the content of the array A as below:
A.splice(0, A.length);
The answers that have no less that 2739 upvotes by now are misleading and incorrect.
The question is: "How do you empty your existing array?" E.g. for A = [1,2,3,4].
Saying "A = [] is the answer" is ignorant and absolutely incorrect. [] == [] is false.
This is because these two arrays are two separate, individual objects, with their own two identities, taking up their own space in the digital world, each on its own.
Let's say your mother asks you to empty the trash can.
You don't bring in a new one as if you've done what you've been asked for.
Instead, you empty the trash can.
You don't replace the filled one with a new empty can, and you don't take the label "A" from the filled can and stick it to the new one as in A = [1,2,3,4]; A = [];
Emptying an array object is the easiest thing ever:
A.length = 0;
This way, the can under "A" is not only empty, but also as clean as new!
Furthermore, you are not required to remove the trash by hand until the can is empty! You were asked to empty the existing one, completely, in one turn, not to pick up the trash until the can gets empty, as in:
while(A.length > 0) {
A.pop();
}
Nor, to put your left hand at the bottom of the trash, holding it with your right at the top to be able to pull its content out as in:
A.splice(0, A.length);
No, you were asked to empty it:
A.length = 0;
This is the only code that correctly empties the contents of a given JavaScript array.
Performance test:
http://jsperf.com/array-clear-methods/3
a = []; // 37% slower
a.length = 0; // 89% slower
a.splice(0, a.length) // 97% slower
while (a.length > 0) {
a.pop();
} // Fastest
You can add this to your JavaScript file to allow your arrays to be "cleared":
Array.prototype.clear = function() {
this.splice(0, this.length);
};
Then you can use it like this:
var list = [1, 2, 3];
list.clear();
Or if you want to be sure you don't destroy something:
if (!Array.prototype.clear) {
Array.prototype.clear = function() {
this.splice(0, this.length);
};
}
Lots of people think you shouldn't modify native objects (like Array), and I'm inclined to agree. Please use caution in deciding how to handle this.
You can easily create a function to do that for you, change the length or even add it to native Array as remove() function for reuse.
Imagine you have this array:
var arr = [1, 2, 3, 4, 5]; //the array
OK, just simply run this:
arr.length = 0; //change the length
and the result is:
[] //result
easy way to empty an array...
Also using loop which is not necessary but just another way to do that:
/* could be arr.pop() or arr.splice(0)
don't need to return as main array get changed */
function remove(arr) {
while(arr.length) {
arr.shift();
}
}
There are also tricky way which you can think about, for example something like this:
arr.splice(0, arr.length); //[]
So if arr has 5 items, it will splice 5 items from 0, which means nothing will remain in the array.
Also other ways like simply reassign the array for example:
arr = []; //[]
If you look at the Array functions, there are many other ways to do this, but the most recommended one could be changing the length.
As I said in the first place, you can also prototype remove() as it's the answer to your question. you can simply choose one of the methods above and prototype it to Array object in JavaScript, something like:
Array.prototype.remove = Array.prototype.remove || function() {
this.splice(0, this.length);
};
and you can simply call it like this to empty any array in your javascript application:
arr.remove(); //[]
If you are using
a = [];
Then you are assigning new array reference to a, if reference in a is already assigned to any other variable, then it will not empty that array too and hence garbage collector will not collect that memory.
For ex.
var a=[1,2,3];
var b=a;
a=[];
console.log(b);// It will print [1,2,3];
or
a.length = 0;
When we specify a.length, we are just resetting boundaries of the array and memory for rest array elements will be connected by garbage collector.
Instead of these two solutions are better.
a.splice(0,a.length)
and
while(a.length > 0) {
a.pop();
}
As per previous answer by kenshou.html, second method is faster.
There is a lot of confusion and misinformation regarding the while;pop/shift performance both in answers and comments. The while/pop solution has (as expected) the worst performance. What's actually happening is that setup runs only once for each sample that runs the snippet in a loop. eg:
var arr = [];
for (var i = 0; i < 100; i++) {
arr.push(Math.random());
}
for (var j = 0; j < 1000; j++) {
while (arr.length > 0) {
arr.pop(); // this executes 100 times, not 100000
}
}
I have created a new test that works correctly :
http://jsperf.com/empty-javascript-array-redux
Warning: even in this version of the test you can't actually see the real difference because cloning the array takes up most of the test time. It still shows that splice is the fastest way to clear the array (not taking [] into consideration because while it is the fastest it's not actually clearing the existing array).
Array.prototype.clear = function() {
this.length = 0;
};
And call it: array.clear();
In case you are interested in the memory allocation, you may compare each approach using something like this jsfiddle in conjunction with chrome dev tools' timeline tab. You will want to use the trash bin icon at the bottom to force a garbage collection after 'clearing' the array. This should give you a more definite answer for the browser of your choice. A lot of answers here are old and I wouldn't rely on them but rather test as in #tanguy_k's answer above.
(for an intro to the aforementioned tab you can check out here)
Stackoverflow forces me to copy the jsfiddle so here it is:
<html>
<script>
var size = 1000*100
window.onload = function() {
document.getElementById("quantifier").value = size
}
function scaffold()
{
console.log("processing Scaffold...");
a = new Array
}
function start()
{
size = document.getElementById("quantifier").value
console.log("Starting... quantifier is " + size);
console.log("starting test")
for (i=0; i<size; i++){
a[i]="something"
}
console.log("done...")
}
function tearDown()
{
console.log("processing teardown");
a.length=0
}
</script>
<body>
<span style="color:green;">Quantifier:</span>
<input id="quantifier" style="color:green;" type="text"></input>
<button onclick="scaffold()">Scaffold</button>
<button onclick="start()">Start</button>
<button onclick="tearDown()">Clean</button>
<br/>
</body>
</html>
And you should take note that it may depend on the type of the array elements, as javascript manages strings differently than other primitive types, not to mention arrays of objects. The type may affect what happens.
Use a modified version of Jan's initial suggestion:
var originalLength = A.length;
for (var i = originalLength; i > 0; i--) {
A.pop();
}
Terser:
for (let i = A.length; i > 0;A.pop(),i--) {}
Or here's another take:
while(!A[Symbol.iterator]().next().done)A.shift()
A.splice(0);
I just did this on some code I am working on. It cleared the array.
If you use constants then you have no choice:
const numbers = [1, 2, 3]
You can not reasign:
numbers = []
You can only truncate:
numbers.length = 0
To Empty a Current memory location of an array use: 'myArray.length = 0' or 'myArray.pop() UN-till its length is 0'
length : You can set the length property to truncate an array at any time. When you extend an array by changing its length property, the number of actual elements increases.
pop() : The pop method removes the last element from an array and returns that returns the removed value.
shift() : The shift method removes the element at the zeroeth index and shifts the values at consecutive indexes down, then returns the removed value.
Example:
var arr = ['77'];
arr.length = 20;
console.log("Increasing : ", arr); // (20) ["77", empty × 19]
arr.length = 12;
console.log("Truncating : ", arr); // (12) ["77", empty × 11]
var mainArr = new Array();
mainArr = ['1', '2', '3', '4'];
var refArr = mainArr;
console.log('Current', mainArr, 'Refered', refArr);
refArr.length = 3;
console.log('Length: ~ Current', mainArr, 'Refered', refArr);
mainArr.push('0');
console.log('Push to the End of Current Array Memory Location \n~ Current', mainArr, 'Refered', refArr);
mainArr.poptill_length(0);
console.log('Empty Array \n~ Current', mainArr, 'Refered', refArr);
Array.prototype.poptill_length = function (e) {
while (this.length) {
if( this.length == e ) break;
console.log('removed last element:', this.pop());
}
};
new Array() | [] Create an Array with new memory location by using Array constructor or array literal.
mainArr = []; // a new empty array is addressed to mainArr.
var arr = new Array('10'); // Array constructor
arr.unshift('1'); // add to the front
arr.push('15'); // add to the end
console.log("After Adding : ", arr); // ["1", "10", "15"]
arr.pop(); // remove from the end
arr.shift(); // remove from the front
console.log("After Removing : ", arr); // ["10"]
var arrLit = ['14', '17'];
console.log("array literal « ", indexedItem( arrLit ) ); // {0,14}{1,17}
function indexedItem( arr ) {
var indexedStr = "";
arr.forEach(function(item, index, array) {
indexedStr += "{"+index+","+item+"}";
console.log(item, index);
});
return indexedStr;
}
slice() : By using slice function we get an shallow copy of elements from the original array, with new memory address, So that any modification on cloneArr will not affect to an actual|original array.
var shallowCopy = mainArr.slice(); // this is how to make a copy
var cloneArr = mainArr.slice(0, 3);
console.log('Main', mainArr, '\tCloned', cloneArr);
cloneArr.length = 0; // Clears current memory location of an array.
console.log('Main', mainArr, '\tCloned', cloneArr);
I'm surprised no one has suggested this yet:
let xs = [1,2,3,4];
for (let i in xs)
delete xs[i];
This yields an array in quite a different state from the other solutions. In a sense, the array has been 'emptied':
xs
=> Array [ <4 empty slots> ]
[...xs]
=> Array [ undefined, undefined, undefined, undefined ]
xs.length
=> 4
xs[0]
=> ReferenceError: reference to undefined property xs[0]
You can produce an equivalent array with [,,,,] or Array(4)

How to split array values using angularjs?

How to split array values using 'angularjs.split' method? It is not working here:
var items =["Regular Servicing & Maintenance","Faults (Interior & Exterior)"];
console.log(items.split(',');
Well, your question is confusing on a number of levels. For one, there isn't an AngularJS function that I'm seeing in the documentation for split.
There's a JavaScript method called split(), but it's used to split a string into an array of substrings, per the linked documentation.
For another, you're already instantiating the items variable with an array of strings though, so you're not really going to get anything from that that you don't already have in the initial value.
Split Method
Now, if you had a string like the following example, you could split that by the commas and yield an array similar to what you've got in your question:
var str = "Apples, Bananas, Cherries";
var arr = str.split(', '); //Note the space as well
console.log(arr); //Yields ["Apples", "Bananas", "Cherries"]
Join Method
But if you're looking for the inverse and you're rather looking to join these into a comma-separated string, you might look at the join() JavaScript method that would look like the following (continued from above):
var result = arr.join(', '); //Note the space again
console.log(result); //Apples, Bananas, Cherries
IndexOf Method
To match the comment you left after I posted this though, if you're looking for the index value of the array that matches a given string, look at the indexOf() method, per the following (again, building from the above example):
var index = arr.indexOf('Bananas'); //Yields 1
var indexRes = arr[index]; //Yields 'Bananas'
If you're looking for something else, you're going to need to clarify the original question.
The below code represents JavaScript code
var items = ["Regular Servicing & Maintenance", "Faults (Interior & Exterior)"];
for (var i = 0; i < items.length; i++) {
console.log("Input:-" + items[i])
console.log("Output:-" + items[i].split('&'));
}
Input: -Regular Servicing & Maintenance
Output: -Regular Servicing, Maintenance
Input: -Faults(Interior & Exterior)
Output: -Faults(Interior, Exterior)
How to split array values using angularJs
$scope.items = [{
'item': 'Regular Servicing & Maintenance'
}, {
'item': 'Faults (Interior & Exterior)'
}]
$scope.array = [];
angular.forEach($scope.items, function(value, key) {
var splitLength = value.item.split('&').length;
for (var i = 0; i < splitLength; i++) {
$scope.array.push(value.item.split('&')[i]);
}
});
console.log($scope.array)

How do I empty an array in JavaScript?

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
Is there a way to empty an array and if so possibly with .remove()?
For instance,
A = [1,2,3,4];
How can I empty that?
Ways to clear an existing array A:
Method 1
(this was my original answer to the question)
A = [];
This code will set the variable A to a new empty array. This is perfect if you don't have references to the original array A anywhere else because this actually creates a brand new (empty) array. You should be careful with this method because if you have referenced this array from another variable or property, the original array will remain unchanged. Only use this if you only reference the array by its original variable A.
This is also the fastest solution.
This code sample shows the issue you can encounter when using this method:
var arr1 = ['a','b','c','d','e','f'];
var arr2 = arr1; // Reference arr1 by another variable
arr1 = [];
console.log(arr2); // Output ['a','b','c','d','e','f']
Method 2 (as suggested by Matthew Crumley)
A.length = 0
This will clear the existing array by setting its length to 0. It also works when using "strict mode" in ECMAScript 5 because the length property of an array is a read/write property.
Method 3 (as suggested by Anthony)
A.splice(0,A.length)
Using .splice() will work perfectly, but since the .splice() function will return an array with all the removed items, it will actually return a copy of the original array. Benchmarks suggest that this has no effect on performance whatsoever.
Method 4 (as suggested by tanguy_k)
while(A.length > 0) {
A.pop();
}
This solution is not very succinct, and it is also the slowest solution, contrary to earlier benchmarks referenced in the original answer.
Performance
Of all the methods of clearing an existing array, methods 2 and 3 are very similar in performance and are a lot faster than method 4. See this benchmark.
As pointed out by Diadistis in their answer below, the original benchmarks that were used to determine the performance of the four methods described above were flawed. The original benchmark reused the cleared array so the second iteration was clearing an array that was already empty.
The following benchmark fixes this flaw: http://jsben.ch/#/hyj65. It clearly shows that methods #2 (length property) and #3 (splice) are the fastest (not counting method #1 which doesn't change the original array).
This has been a hot topic and the cause of a lot of controversy. There are actually many correct answers and because this answer has been marked as the accepted answer for a very long time, I will include all of the methods here.
If you need to keep the original array because you have other references to it that should be updated too, you can clear it without creating a new array by setting its length to zero:
A.length = 0;
Here the fastest working implementation while keeping the same array ("mutable"):
function clearArray(array) {
while (array.length > 0) {
array.pop();
}
}
FYI it cannot be simplified to while (array.pop()): the tests will fail.
FYI Map and Set define clear(), it would have seem logical to have clear() for Array too.
TypeScript version:
function clearArray<T>(array: T[]) {
while (array.length > 0) {
array.pop();
}
}
The corresponding tests:
describe('clearArray()', () => {
test('clear regular array', () => {
const array = [1, 2, 3, 4, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
test('clear array that contains undefined and null', () => {
const array = [1, undefined, 3, null, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
});
Here the updated jsPerf: http://jsperf.com/array-destroy/32 http://jsperf.com/array-destroy/152
jsPerf offline. Similar benchmark: https://jsben.ch/hyj65
A more cross-browser friendly and more optimal solution will be to use the splice method to empty the content of the array A as below:
A.splice(0, A.length);
The answers that have no less that 2739 upvotes by now are misleading and incorrect.
The question is: "How do you empty your existing array?" E.g. for A = [1,2,3,4].
Saying "A = [] is the answer" is ignorant and absolutely incorrect. [] == [] is false.
This is because these two arrays are two separate, individual objects, with their own two identities, taking up their own space in the digital world, each on its own.
Let's say your mother asks you to empty the trash can.
You don't bring in a new one as if you've done what you've been asked for.
Instead, you empty the trash can.
You don't replace the filled one with a new empty can, and you don't take the label "A" from the filled can and stick it to the new one as in A = [1,2,3,4]; A = [];
Emptying an array object is the easiest thing ever:
A.length = 0;
This way, the can under "A" is not only empty, but also as clean as new!
Furthermore, you are not required to remove the trash by hand until the can is empty! You were asked to empty the existing one, completely, in one turn, not to pick up the trash until the can gets empty, as in:
while(A.length > 0) {
A.pop();
}
Nor, to put your left hand at the bottom of the trash, holding it with your right at the top to be able to pull its content out as in:
A.splice(0, A.length);
No, you were asked to empty it:
A.length = 0;
This is the only code that correctly empties the contents of a given JavaScript array.
Performance test:
http://jsperf.com/array-clear-methods/3
a = []; // 37% slower
a.length = 0; // 89% slower
a.splice(0, a.length) // 97% slower
while (a.length > 0) {
a.pop();
} // Fastest
You can add this to your JavaScript file to allow your arrays to be "cleared":
Array.prototype.clear = function() {
this.splice(0, this.length);
};
Then you can use it like this:
var list = [1, 2, 3];
list.clear();
Or if you want to be sure you don't destroy something:
if (!Array.prototype.clear) {
Array.prototype.clear = function() {
this.splice(0, this.length);
};
}
Lots of people think you shouldn't modify native objects (like Array), and I'm inclined to agree. Please use caution in deciding how to handle this.
You can easily create a function to do that for you, change the length or even add it to native Array as remove() function for reuse.
Imagine you have this array:
var arr = [1, 2, 3, 4, 5]; //the array
OK, just simply run this:
arr.length = 0; //change the length
and the result is:
[] //result
easy way to empty an array...
Also using loop which is not necessary but just another way to do that:
/* could be arr.pop() or arr.splice(0)
don't need to return as main array get changed */
function remove(arr) {
while(arr.length) {
arr.shift();
}
}
There are also tricky way which you can think about, for example something like this:
arr.splice(0, arr.length); //[]
So if arr has 5 items, it will splice 5 items from 0, which means nothing will remain in the array.
Also other ways like simply reassign the array for example:
arr = []; //[]
If you look at the Array functions, there are many other ways to do this, but the most recommended one could be changing the length.
As I said in the first place, you can also prototype remove() as it's the answer to your question. you can simply choose one of the methods above and prototype it to Array object in JavaScript, something like:
Array.prototype.remove = Array.prototype.remove || function() {
this.splice(0, this.length);
};
and you can simply call it like this to empty any array in your javascript application:
arr.remove(); //[]
If you are using
a = [];
Then you are assigning new array reference to a, if reference in a is already assigned to any other variable, then it will not empty that array too and hence garbage collector will not collect that memory.
For ex.
var a=[1,2,3];
var b=a;
a=[];
console.log(b);// It will print [1,2,3];
or
a.length = 0;
When we specify a.length, we are just resetting boundaries of the array and memory for rest array elements will be connected by garbage collector.
Instead of these two solutions are better.
a.splice(0,a.length)
and
while(a.length > 0) {
a.pop();
}
As per previous answer by kenshou.html, second method is faster.
There is a lot of confusion and misinformation regarding the while;pop/shift performance both in answers and comments. The while/pop solution has (as expected) the worst performance. What's actually happening is that setup runs only once for each sample that runs the snippet in a loop. eg:
var arr = [];
for (var i = 0; i < 100; i++) {
arr.push(Math.random());
}
for (var j = 0; j < 1000; j++) {
while (arr.length > 0) {
arr.pop(); // this executes 100 times, not 100000
}
}
I have created a new test that works correctly :
http://jsperf.com/empty-javascript-array-redux
Warning: even in this version of the test you can't actually see the real difference because cloning the array takes up most of the test time. It still shows that splice is the fastest way to clear the array (not taking [] into consideration because while it is the fastest it's not actually clearing the existing array).
Array.prototype.clear = function() {
this.length = 0;
};
And call it: array.clear();
In case you are interested in the memory allocation, you may compare each approach using something like this jsfiddle in conjunction with chrome dev tools' timeline tab. You will want to use the trash bin icon at the bottom to force a garbage collection after 'clearing' the array. This should give you a more definite answer for the browser of your choice. A lot of answers here are old and I wouldn't rely on them but rather test as in #tanguy_k's answer above.
(for an intro to the aforementioned tab you can check out here)
Stackoverflow forces me to copy the jsfiddle so here it is:
<html>
<script>
var size = 1000*100
window.onload = function() {
document.getElementById("quantifier").value = size
}
function scaffold()
{
console.log("processing Scaffold...");
a = new Array
}
function start()
{
size = document.getElementById("quantifier").value
console.log("Starting... quantifier is " + size);
console.log("starting test")
for (i=0; i<size; i++){
a[i]="something"
}
console.log("done...")
}
function tearDown()
{
console.log("processing teardown");
a.length=0
}
</script>
<body>
<span style="color:green;">Quantifier:</span>
<input id="quantifier" style="color:green;" type="text"></input>
<button onclick="scaffold()">Scaffold</button>
<button onclick="start()">Start</button>
<button onclick="tearDown()">Clean</button>
<br/>
</body>
</html>
And you should take note that it may depend on the type of the array elements, as javascript manages strings differently than other primitive types, not to mention arrays of objects. The type may affect what happens.
Use a modified version of Jan's initial suggestion:
var originalLength = A.length;
for (var i = originalLength; i > 0; i--) {
A.pop();
}
Terser:
for (let i = A.length; i > 0;A.pop(),i--) {}
Or here's another take:
while(!A[Symbol.iterator]().next().done)A.shift()
A.splice(0);
I just did this on some code I am working on. It cleared the array.
If you use constants then you have no choice:
const numbers = [1, 2, 3]
You can not reasign:
numbers = []
You can only truncate:
numbers.length = 0
To Empty a Current memory location of an array use: 'myArray.length = 0' or 'myArray.pop() UN-till its length is 0'
length : You can set the length property to truncate an array at any time. When you extend an array by changing its length property, the number of actual elements increases.
pop() : The pop method removes the last element from an array and returns that returns the removed value.
shift() : The shift method removes the element at the zeroeth index and shifts the values at consecutive indexes down, then returns the removed value.
Example:
var arr = ['77'];
arr.length = 20;
console.log("Increasing : ", arr); // (20) ["77", empty × 19]
arr.length = 12;
console.log("Truncating : ", arr); // (12) ["77", empty × 11]
var mainArr = new Array();
mainArr = ['1', '2', '3', '4'];
var refArr = mainArr;
console.log('Current', mainArr, 'Refered', refArr);
refArr.length = 3;
console.log('Length: ~ Current', mainArr, 'Refered', refArr);
mainArr.push('0');
console.log('Push to the End of Current Array Memory Location \n~ Current', mainArr, 'Refered', refArr);
mainArr.poptill_length(0);
console.log('Empty Array \n~ Current', mainArr, 'Refered', refArr);
Array.prototype.poptill_length = function (e) {
while (this.length) {
if( this.length == e ) break;
console.log('removed last element:', this.pop());
}
};
new Array() | [] Create an Array with new memory location by using Array constructor or array literal.
mainArr = []; // a new empty array is addressed to mainArr.
var arr = new Array('10'); // Array constructor
arr.unshift('1'); // add to the front
arr.push('15'); // add to the end
console.log("After Adding : ", arr); // ["1", "10", "15"]
arr.pop(); // remove from the end
arr.shift(); // remove from the front
console.log("After Removing : ", arr); // ["10"]
var arrLit = ['14', '17'];
console.log("array literal « ", indexedItem( arrLit ) ); // {0,14}{1,17}
function indexedItem( arr ) {
var indexedStr = "";
arr.forEach(function(item, index, array) {
indexedStr += "{"+index+","+item+"}";
console.log(item, index);
});
return indexedStr;
}
slice() : By using slice function we get an shallow copy of elements from the original array, with new memory address, So that any modification on cloneArr will not affect to an actual|original array.
var shallowCopy = mainArr.slice(); // this is how to make a copy
var cloneArr = mainArr.slice(0, 3);
console.log('Main', mainArr, '\tCloned', cloneArr);
cloneArr.length = 0; // Clears current memory location of an array.
console.log('Main', mainArr, '\tCloned', cloneArr);
I'm surprised no one has suggested this yet:
let xs = [1,2,3,4];
for (let i in xs)
delete xs[i];
This yields an array in quite a different state from the other solutions. In a sense, the array has been 'emptied':
xs
=> Array [ <4 empty slots> ]
[...xs]
=> Array [ undefined, undefined, undefined, undefined ]
xs.length
=> 4
xs[0]
=> ReferenceError: reference to undefined property xs[0]
You can produce an equivalent array with [,,,,] or Array(4)

Categories

Resources