Find the smallest number in a file

Hello,
I have a file like below:

1
-1
2
-2
3
4
-4

I want to find the smallest number in this file and I wrote the following program:

function smaller()
    small = 0
    for line in eachline("file.txt")
        if (small == 0)
        small = line
        elseif (small > line)
            small = line
        end
    end
    println(small)
end
smaller()

I am a newbie and I want to know where my problem is and I don’t want to use other methods.

Thank you.

Some tips:

  • is line from eachline a number or a string?
  • the only case you’d want to update small with line is if small > line, so your if and else statements could be simpler
  • traditionally, one might expect your smaller function to accept the file name and return the smallest integer (i.e. not print it out).
  • I don’t know for sure, but I bet that the error messages you got would have helped you in improving this code. Maybe you can match the messages to some of these tips?

Hi,
Thank you so much for you reply.
The file contains the same numbers that I wrote above. Ah, numbers are string:

 println(typeof(line))
> string

I changed the code to below, but I got an error:

small = parse(Int, line)

Why?

I do not know:

julia> for line in eachline("file.txt")
       i = parse(Int, line)
       println(i)
       end
1
-1
2
-2
3
4
-4

is there an empty line in that file?

What precisely did you change? If you just replaced the two occurrences of small = line by small = parse(Int, line), then the comparison small > line would yield an error, as you are comparing an Int (small) to a String (line).

Hi,
Thank you so much for your note.
I changed the code as follows:

function smaller()
    small = 0
    for line in eachline("file.txt")
        if (small == 0)
        small = parse(Int,line)
        elseif (small > parse(Int,line))
            small = parse(Int,line)
        end
    end
    println(small)
end
smaller()

Another note for style: You can simplify your logic if you initialize small with the greatest possible number. Then you do don’t need the if small == 0 stuff and only need the comparison :slight_smile:

You can get the biggest value of a datatype with typemax(datatype) so in your case that’s typemax(Int).

The need for parsing has already been mentioned, but I thought I’d just add that you can solve this in a one-liner:

julia> minimum(l -> parse(Int, l), eachline("/tmp/numlist"), init=0)
-4

Initializing with zero seems like a bad idea. What if all the numbers in the file are positive?

I’m just matching the behavior in the original code, which initialised small = 0. Personally I’d go with:

minimum(Iterators.filter(!isnothing, Iterators.map(l -> tryparse(Int, l), eachline("file")), init=typemin(Int))

The original code overwrites the initialisation in the first iteration step, which minimum(..., init=...) does not. So this is not equivalent, and the original code (with parse) is correct (though not particularly concise).

You probably meant typemax(Int), cf. @abraemer 's post. Alternatively, you could simply leave out the explicit init.

I did indeed.

Independently of the one-liners above, which might be confusing, the simple loop is probably written like this (and it is perfectly fine):

function smaller(file) # provide the file as a parameter to the function
    small = typemax(Int)
    for line in eachline(file)
        small = min(small, parse(Int, line))
    end
    return small
end

To be run with:

julia> smaller("file.txt")

And there’s nothing wrong in substituting the min(...) by

    value = parse(Int,line)
    if value < small
        small = value
    end

My philosophy is to tell people when their code/question is wrong or misguided, rather than to just give them what they are asking for😉