1

I'm trying to solve a coderbyte challenge in which I have to compare letters in each word in a string and return the word with the most duplicated letters. EX: "Hello World" -> "Hello"

I'm still trying to solve the problem but I ran into some bizarre behavior involving Array.prototype.pop();

Here is my code:

function LetterCountI(str) { 

    str = str.split(" ");

    var largest = "";
    var letterCount = 0;

    for (var i = 0; i <str.length;i++) {
        letterCount = findMatches(str[i].split(""));  
    }

    function findMatches(array) {
        var letterCount = 0;
        while (array.length) {
            var letter = array.pop();
            var counter = 0;
            var arrayCopy = array;
            letterCount += compareRecursive(letter, arrayCopy, counter);
        }
        return letterCount;
    }

    function compareRecursive(letter, a, counter) {
        if (a.length === 0) {
            return counter;  
        }
        var n = a.pop();
        if (letter === n) {
            counter++;  
        }
        return compareRecursive(letter, a, counter);
    }
    return letterCount;     
}

What is happening is I am using Array.prototype.pop() in my compareRecursive function to return the last index of the array and to make the array smaller so I could loop through the whole string. I call compareRecursive in my findMatches function. After I call compareRecursive the array variable and the arrayCopy variables get emptied. From my understanding of scope the compareRecursive function should have its own copy of the array since I'm passing it in as a parameter, why is Array.prototype.pop() affecting the array and arrayCopy variables in my findMatches function?

When I change the line

var n = a.pop();

To:

var n = a[0];
a = a.slice(1);

The array and arrayCopy variables in the findMatches functions aren't affected. Why is this?

2
  • "compareRecursive function should have its own copy of the array since I'm passing it in as a parameter". No, parameters are passed by value, and for objects or arrays, the value is a reference. Commented Aug 7, 2015 at 14:45
  • Ok, that makes sense. But why does the "array" variable in findMatches also get affected by compareRecursives's "a.pop()" when I pass in "arrayCopy"? Commented Aug 7, 2015 at 15:04

1 Answer 1

2

pop() mutates the existing array, removing the last item. slice() returns a shallow copy of the array and does not the original array.

// pop
var foo = [1, 2, 3];
var three = foo.pop(); // "pops out" 3 from the array
// foo = [1, 2]
// three = 3;

// slice
var foo = [1, 2, 3];
var three = foo.slice(-1)[0]; // Creates new array with 3 inside (ie. [3])
// foo = [1, 2, 3];
// three = 3;

If you want to use pop without affecting the original array (because pop is just so convenient), you can use slice to create a copy of the array and pop that instead.

var originalArray = [1, 2, 3];
var arrayClone = originalArray.slice();
var poppedItem = arrayClone.pop();
// originalArray = [1, 2, 3];
// arrayClone = [1, 2];
// poppedItem = 3;
Sign up to request clarification or add additional context in comments.

3 Comments

Why doesn't var arrayClone = originalArray make a copy of the array? Why do you have to use arrayClone = originalArray.slice()?
@richardckastl Unlike primitives (string, numbers, booleans) Objects (which includes arrays and functions) are never copied. Assigning a variable an object will only make the variable "point" to the same object.
Thank you, this makes more sense now.

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.