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?
1 Like

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?

1 Like

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).

1 Like

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).

2 Likes

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
4 Likes

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))
1 Like

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.

1 Like

I did indeed.

1 Like

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
1 Like

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😉

1 Like