2

I'm having trouble understanding how I can traverse between the functions, passing arrays between them, a full day of 'undefined' or 'this is not a function' has me pulling my hair out.

I'm currently doing a challenge on codewars, The task is seemingly simple, take a string that has open and closed braces and check them to see if they're opening/closing in the correct order. However, for some reason the console.log is not returning anything in this challenge so I'm having to do it blind.

Here's the first function, I set all the variables and the arrays and pass it on to the next function.

function validBraces(braces) {
   var braceAr = [];
   braceAr = braces.split('');
   var testAr = []; // array to be used for testing the order
   var i = 0; // iterator for the loop in analyse() function
   analyse(...braceAr,...testAr,i); //send the arrays to the function!
}

In the last line in the function above, I'm trying to pass the arrays to the next function, I don't want to create them inside the next function since there is a third function that does the check, sending it back again to the second (analyse). I'm using a spread operator in this 'version', however, I've exhausted my understanding and resources, so I reach out to gain a better understanding. Can someone explain how I can pass these arrays to the functions. I've tried to apply things from explanations I've found but I feel I may be missing something fundamental that is limiting me.

The rest of the code is below, it may not be relevant, but it's there just in case. I'd love to solve this so try to not give too much away ;)

function analyse(braceAr,testAr,i) {

   for(l = braceAr.length; i<l ;) {
     switch(braceAr[i]) {

       case '[':
           testAr.push("]");
           break;
       case '{':
           testAr.push("}");
           break;
       case '(':
           testAr.push(")");
           break;
       case ']':
           check(...braceAr,...testAr,i);
           break;
       case '}':
           check(...braceAr,...testAr,i);
           break;
       case ')':
           check(...braceAr,...testAr,i);
           break;

      } //close switch
    } //close loop


return (testAr.length = 0 ? true : false);

  } //close function 

As you can see, I intend to switch through each element in the array, and if it's an open brace, I'll push the corresponding closing brace into an array to be compared in the third function check()

function check(braceAr,testAr,i) {   

    if(testAr.pop() === braceAr[i])
      {
        i++;
        analyse(...braceAr,...testAr,i);

      } else { return false; }

} //close function

If the most recent element added is the same as the closing brace, we have a matching open/close brace. Increment the index and go back to analysing the rest of the braces.

How does it look?

Jay Jenkins
  • 413
  • 1
  • 5
  • 15
  • This might be useful to you, assuming it's anywhere close to being related to order of your JS function calls - https://stackoverflow.com/questions/7609276/javascript-function-order-why-does-it-matter – Adam Aug 17 '18 at 18:23
  • IIRC, it's just good practice to have the functions correctly ordered since lints will throw errors. I've played around with the order to no avail. I'll tidy it after, thanks – Jay Jenkins Aug 17 '18 at 18:26
  • `braceAr` and `testAr` are already arrays. There is no need to use the `...` spread operator when passing them as parameters. – Alexander van Oostenrijk Aug 17 '18 at 18:27
  • @JayJenkins my comment was a shot in the dark, I'm no JS expert by any means. Looks like some proper experts have chimed in ;) – Adam Aug 17 '18 at 18:29

3 Answers3

1

Don't use ..., that's spreading the array contents into separate arguments to the function, as if you'd written:

analyse(braceAr[0], braceAr[1], braceArr[2], /* rest of braceAr */,
        testAr[0], testAr[1], testAr[2], /* rest of testAr */, i);

Just write:

analyse(braceAr,testAr,i);

You have the same problem when calling check().

When check() calls analyse() recursively, it needs to return its value; see Recursive function does not return specified value.

And you never use the return value of check() in analyse(), so I'm not sure what the point of it is at all. I'm not sure what it's trying to do and how the return value should be used.

validBraces("a[foo(bar).baz]");

function validBraces(braces) {
  var braceAr = [];
  braceAr = braces.split('');
  var testAr = []; // array to be used for testing the order
  var i = 0; // iterator for the loop in analyse() function
  analyse(braceAr, testAr, i); //send the arrays to the function!
  console.log(testAr);
}

function check(braceAr, testAr, i) {

  if (testAr.pop() === braceAr[i]) {
    i++;
    return analyse(braceAr, testAr, i);
  } else {
    return false;
  }

} //close function

function analyse(braceAr, testAr, i) {

  for (l = braceAr.length; i < l; i++) {
    switch (braceAr[i]) {

      case '[':
        testAr.push("]");
        break;
      case '{':
        testAr.push("}");
        break;
      case '(':
        testAr.push(")");
        break;
      case ']':
        check(braceAr, testAr, i);
        break;
      case '}':
        check(braceAr, testAr, i);
        break;
      case ')':
        check(braceAr, testAr, i);
        break;

    } //close switch
  } //close loop

  return (testAr.length = 0 ? true : false);
} //close function
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • The thing is, when I take the spread operator away, I receive a fatal error. I honestly only presumed that it was the arrays not passing, not having a console to check my lines is a nightmare for a beginner. – Jay Jenkins Aug 17 '18 at 18:30
  • 1
    You have an infinite loop in `analyse`, since you never increment `i`. You also never use the return value of `check()`, and when it calls `analyse()` it doesn't return the value. – Barmar Aug 17 '18 at 18:39
0

The analyse(...braceAr,...testAr,i) won't pass the arrays braceAr and testAr to function analyse(braceAr,testAr,i) {, but uses their content as arguments for the function:

var arrA = [1,2]
var arrB = [3,4]

function test(a, b, c, d) {
  console.log(a, ',', b, ',', c, ',', d)
}

test(...arrA, ...arrB)

If you want to pass the array you have to remove the spreading operator ... and just write analyse(braceAr, testAr,i).

t.niese
  • 39,256
  • 9
  • 74
  • 101
0

Using the spread operator (...) passes each array element as an argument. That way, when you try to use the push() function, it generates an error.

function faultyPasser(string) {
  var charArr = string.split('');
  logChars(...charArr);
}

function logChars(charArr) {
  for (i in charArr)
    console.log(charArr[i]);
}

faultyPasser("Bad code.");

Rewrite all of your function calls with arrays to get rid of the spread operator. It should work as long as there are no other bugs.

Brendon Shaw
  • 297
  • 5
  • 21