Andrew OZEKI
Andrew OZEKI

Reputation: 63

Finding the shortest word in a string

I'm new to coding and I'm working on a question that asks to find the shortest word within a sentence. I'm confused what the difference between:

def find_short(s):
    for x in s.split():
        return min(len(x)) 

and

def find_short(s):
    return min(len(x) for x in s.split())

is, because the former gives me an error and the latter seems to work fine. Are they not virtually the same thing?

Upvotes: 5

Views: 3074

Answers (5)

Andres Salgado
Andres Salgado

Reputation: 243

Yes, the examples given are very different.

 

The first example effectively says:

Take the string s, split it by spaces, and then take each word, x, found and return the minimum value of just the length of x.

 

The second example effectively says:

Find the minimum value in the list generated by len(x) for x in s.split().

 

That first example generates an error because the min function expects to compare at least 2 or more elements, and only 1 is provided.

That second example works because the list that is generated by len(x) for x in s.split() converts a string, like say "Python types with ducks?" to a list of word lengths (in my example, it would convert the string to [6, 5, 4, 6]). That list that is generated (this is also why it's called a generator), is what the min function then uses to find the minimum value inside said list.

 

Another way to write that first example so that it works like you would expect is like this

def find_short(s):
    min_length = float("inf")

    for x in s.split():
        if len(x) < min_length:
            min_length = len(x)

    return min_length

However, notice how you have to keep track of a variable that you do not have to define using the list generator method in your second example. Although this is not a big deal when you are learning programming for the first time, it becomes a bigger deal when you start making larger, more complex programs.

 

Sidenote:

Any value that follows the return keyword is what a function "outputs", and thus no more code gets executed.

For example, in your first example (and assuming that the error was not generated), your loop would only ever execute once regardless of the string you give it because it does not check that you actually have found the value you want. What I mean by that is that any time your code encounters a return statement, it means that your function is done.

That is why in my example find_short function, I have an if statement to check that I have the value that I want before committing to the return statement that exits the function entirely.

Upvotes: 1

marcelotokarnia
marcelotokarnia

Reputation: 386

There is mainly two mistakes here.

First of, seems you are returning the length of the string, not the string itself.

So your function will return 4 instead of 'book', for example.

I will get into how you can fix it in short.

But answering your question:

min() is a function that expects an iterable (entities like array).

In your first method, you are splitting the text, and calling return min(len(word)) for each word.

So, if the call was successfully, it would return on the first iteration.

But it is not successfully because min(3) throws an exception, 3 is not iterable.

On your second approach you are creating a list of parameters to min function.

So your code first resolves len(x) for x in s.split() returning something like 3,2,3,4,1,3,5 as params for min, which returns the minimum value.

If you would like to return the shortest word, you could try:

def find_short(s):
    y = s.split()
    y.sort(key=lambda a: len(a))
    return y[0]

Upvotes: 0

Eugene Primako
Eugene Primako

Reputation: 2817

No, they are not the same thing.

In first piece of code you are entering for cycle and trying to calculate min of the first word's length. min(5) doesn't make sense, does it? And even if it could be calculated, return would have stopped executing this function (other words' lengths would not have been taken into consideration).

In second one, len(x) for x in s.split() is a generator expression yielding the lengths of all the words in your sentence. And min will calculate the minimal element of this sequence.

Upvotes: 1

Liora Haydont
Liora Haydont

Reputation: 1283

The function min takes an array as parameter.

On your 1st block, you have

def find_short(s):
    for x in s.split():
        return min(len(x)) 

min is called once on the length of the 1st word, so it crashes because it's expecting an array

You second block is a little different

def find_short(s):
    return min(len(x) for x in s.split())

Inside min, you have len(x) for x in s.split() which will return an array of all the lengths and give it to min. Then, with this array, min will be able to return the smallest.

Upvotes: 1

UltraInstinct
UltraInstinct

Reputation: 44444

Are they not virtually the same thing?

No, they are not the same thing. If s equals "hello world", in the first iteration, x would be "hello". And there are two things wrong here:

  • You are trying to return in the very first iteration rather than going over all the elements (words) to find out what's the shortest.
  • min(len(x)) is like saying min(5) which is not only an bad parameter to pass to min(..) but also doesn't make sense. You'd want to pass a list of elements from which min will calculate the minimum.

The second approach is actually correct. See this answer of mine to get an idea of how to interpret it. In short, you are calculating length of every word, putting that into a list (actually a generator), and then asking min to run its minimum computation on it.

There's an easier approach to see why your second expression works. Try printing the result of the following:

print([len(x) for x in s.split()])

Upvotes: 3

Related Questions