Line feed by spaces

hello, can you tell me how to make a better function that performs line feeds by spaces, than what I did with my natural science education, i, j, l and += 1 ?

function feed_lines(str::String, l::Int)
    chars = collect(str)
    i = findfirst(' ', str)
    j = 1
    for (index, char) in pairs(chars)
        if char == ' '
            i = index
        end
        if j > l
            chars[i] = '\n'
            j = index - i
        end
        j += 1
    end
    return join(chars)
end

although it seems not so bad

Could you explain what is the role of integer l?

In my limited understanding the following seems to produce similar results:

feed_lines2(str::String) = join(split(str),"\n")
1 Like

this is line length, if line length > l then replace last space (which < l) to ‘\n’

Could you provide a minimum working example (MWE) to illustrate what it is supposed to do?

sure

julia> function feed_lines(str::String, l::Int)
           chars = collect(str)
           i = findfirst(' ', str)
           j = 1
           for (index, char) in pairs(chars)
               if char == ' '
                   i = index
               end
               if j > l
                   chars[i] = '\n'
                   j = index - i
               end
               j += 1
           end
           return join(chars)
       end
feed_lines (generic function with 1 method)

julia> feed_lines("""hello, can you tell me how to make a better function that performs line feeds by spaces, than what I did with my natural science education, i, j, l and += 1 ?""", 30) |> println

hello, can you tell me how to
make a better function that
performs line feeds by spaces,
than what I did with my
natural science education, i,
j, l and += 1 ?
1 Like

Just an idea (not quite doing what you ask for):

julia> join(join.(Iterators.partition(s, 30) |> collect, ""), "\n") |> println
hello, can you tell me how to
make a better function that pe
rforms line feeds by spaces, t
han what I did with my natural
 science education, i, j, l an
d += 1 ?

where s is your example string.

(Do we have an efficient “word iterator” somewhere?)

2 Likes

This is rather compact:

julia> function feed_lines2(str, l)
           line_breaks = findnext.(' ', str, l:l:length(str))
           join([i in line_breaks ? '\n' : c for (i,c) in pairs(str)])
       end
feed_lines2 (generic function with 1 method)

julia> feed_lines2("""hello, can you tell me how to make a better function that performs line feeds by spaces, than what I did with my natural science education, i, j, l and += 1 ?""", 30) |> println
hello, can you tell me how to
make a better function that performs
line feeds by spaces, than
what I did with my natural
science education, i, j, l and
+= 1 ?

However, I think it will be (a bit) less efficient than your variant.

2 Likes

A version that uses SubString and also returns the number of rows printed:

function feed_lines3(str, n)
    ix = [1; findall(' ', str); length(str)]
    j1 = zero(ix)
    j2 = zero(ix)
    nr = 1
    j1[1] = 1
    for i in 2:length(ix)
        if ix[i] - j1[nr] > n
            j2[nr] = ix[i-1]
            nr += 1
            j1[nr] = ix[i-1] + 1
        elseif i == length(ix)
            j2[nr] = ix[end]
        end
    end
    join(SubString.(str, view(j1,1:nr), view(j2,1:nr)), "\n"), nr
end

println(feed_lines3(str, 30)[1])
# result:
hello, can you tell me how to
make a better function that
performs line feeds by spaces,
than what I did with my
natural science education, i,
j, l and += 1 ?

This version should be further optimized, as only one j array seems necessary.

2 Likes

FWIW, a simpler alternative and a bit faster:

function feed_lines4(str, n)
    ix = [1; findall(' ', str); length(str)]
    nx = length(ix)
    j = 1;
    s2 = ""
    for i in 2:nx
        if ix[i] - j > n
            s2 = s2 * view(str,j:ix[i-1]) * "\n"
            j = ix[i-1] + 1
        elseif i == nx
            s2 = s2 * view(str,j:ix[nx]) * "\n"
        end
    end
    return s2
end

println(feed_lines4(str,30))
# result:
hello, can you tell me how to
make a better function that
performs line feeds by spaces,
than what I did with my
natural science education, i,
j, l and += 1 ?

There is also https://github.com/carlobaldassi/TextWrap.jl

4 Likes

@stevengj, the TextWrap.jl package although more general seems for the OP example to be slower than the above solutions (maybe ~3x when comparing using @time run multiple times).