3

Morning ! I'm facing an issue on a freeNumberGenerator function with a basic find usage. The issue is that the first example of code can't return me a free number, if it takes an array like [0, 1, 2, 3] it will always return 0, considering that 0 is not part of the array arr argument. Looks like a basic usage as i said but i can't find [uhuh...] why.

Not Working :

public getFreeNumber(...arr: number[]): number {
        let freeNumber: number = 0;
        let isTaken: boolean = true;

        while (isTaken) {
            if (arr.find(n => n === freeNumber)) {
                ++freeNumber;
            } else {
                isTaken = false;
            }
        }
        return freeNumber;
    }

Working :

public getFreeNumber(...arr: number[]): number {
        let freeNumber: number = 0;
        let isTaken: boolean = true;

        while (isTaken) {
            if (arr.indexOf(freeNumber) !== -1) {
                ++freeNumber;
            } else {
                isTaken = false;
            }
        }
        return freeNumber;
    }

Working :

public getFreeId(arr: Array<IIdentifiable>): number {
        let freeId: number = 0;
        let isTaken: boolean = true;

        while (isTaken) {
            if (arr.find(a => a.id === freeId)) {
                ++freeId;
            } else {
                isTaken = false;
            }
        }
        return freeId;
    }
everblack
  • 361
  • 1
  • 5
  • 11

1 Answers1

3

Well, potentially because Array.prototype.find returns the first number that matches your function. In case the number would 0, it would return 0 and this would be treated as falsy.

You could change the behavior by checking if the find method doesn't return undefined, like so (typescript changes)

public getFreeNumber(...arr: number[]): number {
    let freeNumber: number = 0;
    let isTaken: boolean = true;

    while (isTaken) {
        if (typeof arr.find(n => n === freeNumber) !== 'undefined') {
            ++freeNumber;
        } else {
            isTaken = false;
        }
    }
    return freeNumber;
}

and a sample javascript output would be something like this

function getFreeNumber(arr) {
  let freeNumber = 0;
  let isTaken = true;

  while (isTaken) {
    if (typeof arr.find(n => n === freeNumber) !== 'undefined') {
      ++freeNumber;
    } else {
      isTaken = false;
    }
  }
  return freeNumber;
}

console.log( getFreeNumber([0,1,2,3]) );
Community
  • 1
  • 1
Icepickle
  • 12,689
  • 3
  • 34
  • 48
  • 1
    Oh i see now, so considering your response, the difference with the last example is that it returns me an object `IIdentifiable` and not the id value, `0`, itself. I should have read the documentation again ... And what's the most efficient way to do so/use ? `indexOf`(second example) ? – everblack Feb 10 '17 at 10:14
  • 1
    I think `find` is a perfectly valid command there, I don't really think there is such a big difference in performance (I also don't know what kind of data you should support). Both `find` and `indexOf` will iterate all your values continuously. If it needs to be performant, and you expect lots of values, I would rather suggest you map it into an object, and then search for the free number by checking wether or not that property exist on the mapped object (which would be faster for large arrays, as it wouldn't keep on searching through the full array) – Icepickle Feb 10 '17 at 10:23