0

Write a function called "getLengthOfShortestElement".

Given an array, "getLengthOfShortestElement" returns the length of the shortest string in the given array.

Notes: * It should return 0 if the array is empty.

My code:

 function getLengthOfShortestElement(arr) {

  if (arr.length === 0) return 0;
       return arr.sort(function(a, b){
          return a.length> b.length;
        }).unshift();
}

 getLengthOfShortestElement(['one', 'two', 'three']); // 3

Why is it not passing the test that it should "handle ties" by returning only the first instance of the shortest element. Also, is there a better way of making an empty array return 0?

  • 2
    what do you mean "Why is it not passing the test that it should "handle ties" by returning only the first instance of the shortest element." ? Should it return a length or an instance ? It is unclear – Walle Cyril Oct 27 '16 at 01:36
  • it returns the length of the shortest string in the given array. If more than one element share the same shortest length, it returns the length of only the first one. This is the feedback I get from repl: Failed tests it_should_handle_ties More info Error: Expected 3 to be 2. at n – sopstem2428 Oct 27 '16 at 01:46
  • *"is there a better way of making an empty array return 0?"* - What's wrong with the simple and direct technique that you currently use for that? By the way, your sort function should `return a.length - b.length;` (the comparator isn't supposed to return a boolean). – nnnnnn Oct 27 '16 at 01:54
  • 1
    @Tyler.Borer That doesn't make sense. If multiple elements have the same minimal length, the returned length is still the minimal one regardless from which element you got it. – Bergi Oct 27 '16 at 02:09
  • [Your comparison function is broken](http://stackoverflow.com/q/24080785/1048572). That's likely why it fails some tests. – Bergi Oct 27 '16 at 02:10
  • 1
    You probably want `[0].length` not [`.unshift()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)?! – Bergi Oct 27 '16 at 02:15

6 Answers6

1

This could be done with a reducer.

function getLengthOfShortestElement(arr) {

    if (!arr.length) return 0;

    return arr.reduce(function(prev, current) {

        if (prev === null) return current.length;
        if (current.length < prev) return current.length;

        return prev;
    }, null);
}
Rob Porter
  • 801
  • 8
  • 23
  • `.reduce()` is a good way to do this, but the code you've shown doesn't return the *element*, it returns the element's length. – nnnnnn Oct 27 '16 at 01:59
  • @nnnnnn `if (!arr.length) return 0;` – tom10271 Oct 27 '16 at 01:59
  • 1
    Instead of starting with `null`, you could simply start with `Infinity` and drop that first condition. – Bergi Oct 27 '16 at 02:11
  • @nnnnnn the question is a bit confusing as it does state both `returns the length of the shortest string in the given array` and `returning only the first instance of the shortest element`. It cannot return both so I'm going with the first... but it would be easy to adjust this to return the element by just returning `current` rather than `current.length` within the reducer. – Rob Porter Oct 27 '16 at 02:16
  • Returning the length would be consistent with returning `0` for an empty array, but then the concept of returning the first one in the event of a "tie" wouldn't make sense. The OP's code doesn't actually return the length *or* the element, it is returning the length of the array, because that's what `.unshift()` returns, but I suspect they intended to use `.shift()` to get the first element. – nnnnnn Oct 27 '16 at 02:32
0

Because the Javascript Array.prototype.sort documentation clearly states:

The sort() method sorts the elements of an array in place and returns the array. The sort is not necessarily stable.

In other words, there is no guarantee that elements with the same length will be in the same order in the sorted result, as they were in the original.

Perhaps a better method would be to bypass the possibly-unstable sort and simply process the array yourself. This could be easily done with the following pseudo-code:

def getFirstShortestElement(array):
    if len(array) == 0:
        return 0
    firstSmall = 0
    for index = 1 to len(array) - 1, inclusive:
        if len(array[index]) < len(array[firstSmall]):
            firstSmall = index
    return array[firstSmall]

As an aside, your function is spectacularly misnamed. It does not give you the "LengthOfShortestElement" at all. Function names should reflect what they do, you'll find your code much easier to maintain if you follow that rule :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

It should works for all cases.

function getLengthOfShortestElement(arr){

    if (arr.length === 0) return 0;

    var shortestLength = arr[0].length;
    arr.forEach(function (each) {
        shortestLength = each.length < shortestLength ? each.length : shortestLength;
    });

    return shortestLength;
}
tom10271
  • 4,222
  • 5
  • 33
  • 62
0

I dont get what you mean by "Why is it not passing the test that it should "handle ties" by returning only the first instance of the shortest element".

But returning 0 on empty array, i would do:

function getLengthOfShortestElement(arr){
    if (!arr){return 0}
    //rest of your code
}
Sean W
  • 527
  • 6
  • 15
0

You're using unshift, which prepends an element rather than removing it, and you're missing the length property.

function getLengthOfShortestElement(arr) {
    if (!arr || !arr.length) {return 0;}
    arr = [].concat(arr); // Prevent altering the source array
    return arr.sort(function (a, b) {
      return a.length > b.length;
    }).shift().length;
}

getLengthOfShortestElement(['one', 'two', 'three']); // 3

For long arrays, it's probably faster if you travel the array checking lengths:

function getLengthOfShortestElement(arr) {
    if (!arr || !arr.length) {return 0;}
    var minlength = (""+arr[0]).length;
    for (var i = 1; i < arr.length; i++) {
        var len = (""+arr[i]).length;
        if (len < minlength) {minlength = len;}
    }
    return minlength;
}
Javier Rey
  • 1,539
  • 17
  • 27
0

I think you can do it with reduce method.

 function getLengthOfShortestElement(arr) {
   return arr.length 
   ?  arr.reduce((a, b) => a.length < b.length ? a : b).length
   : 0;
 }
 getLengthOfShortestElement(['one', 'two', 'three']);
Th1
  • 269
  • 2
  • 12