Viet
Viet

Reputation: 6953

Why reduce() skip square brackets?

I have this code:

var isValid = function(s) {
    let arr = [...s];

    arr.reduce((acc, cur) => {
        console.log(`arr in reduce: ${arr}`);
        console.log(`acc: ${acc}`);
        console.log(`cur: ${cur}`);
        if ((acc && cur)
        && (
            (acc === '(' && cur === ')')
            || (acc === '{' && cur === '}')
            || (acc === '[' && cur === ']')
        )) {
            arr.splice(arr.indexOf(acc), 2);
            console.log(`arr after splice: ${arr}`);
            return arr;
        }
        else {
            console.log(`else statement: ${cur}`);
            return cur;
        }
    });

    return arr.length === 0 ? true : false;
};

console.log(isValid("()[]{}"));

It needs to return true if:

My code doesn't pass this test "()[]{}": it always returns [,] and I don't understand why. I've tried using regex, anscii for the square brackets but it doesn't work.

Upvotes: 3

Views: 177

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386730

You could take an object for the expected closing characters and if an open character is found push the expected closing character to a stack.

Otherwise check the popped value against the character.

var isValid = function([...array]) {
        var stack = [],
            open =  { '(': ')', '[': ']', '{': '}' };
        return array.every(c => c in open ? stack.push(open[c]) : c === stack.pop())
            && !stack.length;
    };

console.log(isValid("()[]{}"));
console.log(isValid("(({}[()]))[]{}"));
console.log(isValid("()[]{}}"));
console.log(isValid("["));

Upvotes: 3

Kaddath
Kaddath

Reputation: 6151

Because splice changes the length, you'll notice by looking at your logs that [,] is skipped in the tests because of that (the current index in the reduce steps don't correpond to the array any more). You should probably use a copy instead of the the original array when you splice, and test this array instead:

Note that the way your code is made, it won't work with nested parenthesis/brackets. You should also be careful about the use of indexOf to find the cur, because it will return the first found, which if you change your code, might not correspond to your real cur.

var isValid = function(s) {
    let arr = [...s], copy = [...s];

    arr.reduce((acc, cur) => {
        console.log(`arr in reduce: ${arr}`);
        console.log(`copy in reduce: ${copy}`);
        console.log(`acc: ${acc}`);
        console.log(`cur: ${cur}`);
        if ((acc && cur)
        && (
            (acc === '(' && cur === ')')
            || (acc === '{' && cur === '}')
            || (acc === '[' && cur === ']')
        )) {
            copy.splice(copy.indexOf(acc), 2);
            console.log(`copy after splice: ${copy}`);
            return arr;
        }
        else {
            console.log(`else statement: ${cur}`);
            return cur;
        }
    });

    return copy.length === 0 ? true : false;
};

console.log(isValid("()[]{}"));

Upvotes: 3

Related Questions