0

I converted the following function from JS to Typescript and it works well. However in the line if (!(key * key) in frequencyCounter2) { i get the error: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'."

I tried to typecast key as a number, but to no avail. Is this operation generally not senseful when using typescript?

// The function same accepts two arrays and should return true if every value in the array has its corresponding 
// value squared in the second array. The frequency of values must be the same.
function sameOn(arrA: number[], arrB: number[]): boolean {
    // complexity O(n): If arr is 1000 lines, this runs 2000 times
    if (arrA.length !== arrB.length) {
        return false;
    }
    type CountType = {
        [key: number] : number
    }

    const frequencyCounter1: CountType = {};
    const frequencyCounter2: CountType = {};

    for (const val of arrA) {
        frequencyCounter1[val] = (frequencyCounter1[val] || 0) +1;
    }
    for (const val of arrB) {
        frequencyCounter2[val] = (frequencyCounter2[val] || 0) +1;
    }

    for (const key in frequencyCounter1) {               
        if (!(key * key) in frequencyCounter2) {
            return false;
        }
        if (frequencyCounter2[key * key] !== frequencyCounter1[key]) {
            return false;
        }
    }
    return true;
}

sameOn([1,2,3,2], [4,1,9,4]) // returns true

2 Answers 2

4

This line:

if (!(key * key) in frequencyCounter2) {

looks for a boolean in frequenceCounter2, because key * key creates a number and then !number converts that number to boolean.

If you're trying to check that the key * key key isn't there, you need more ():

if (!((key * key) in frequencyCounter2)) {
//   ^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^−−−−−−−−−

or really, you just need to relocate your first ):

if (!(key * key in frequencyCounter2)) {
// Not here −−−^−−−−−−−−−−−−−−−−−−−−^−− here

since the key * key part of the in expression will be evaluated before the in part.


It sounds like this may well have been a bug in the original JavaScript, which would have checked for "true" or "false" in frequencyCounter2 without raising any complaints. :-)

Sign up to request clarification or add additional context in comments.

Comments

0

The refactored solution is:

export function sameOn(arrA: number[], arrB: number[]): boolean {
    // complexity O(n): If arr is 1000 lines, this runs 2000 times
    if (arrA.length !== arrB.length) {
        return false;
    }
    type CountType = {
        [key: number] : number
    }

    const frequencyCounter1: CountType = {};
    const frequencyCounter2: CountType = {};

    for (const val of arrA) {
        frequencyCounter1[val] = (frequencyCounter1[val] || 0) +1;
    }
    for (const val of arrB) {
        frequencyCounter2[val] = (frequencyCounter2[val] || 0) +1;
    }
    
    for (const key in frequencyCounter1) {
        const squaredKey = Number(key)*Number(key);
                  
        if (!(String(squaredKey) in frequencyCounter2)) {
            return false;
        }
        if (frequencyCounter2[squaredKey] !== frequencyCounter1[key]) {
            return false;
        }
    }
    return true;
}

Comments

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.