I’d try to use the built-in tools for iterating and transforming stuff to
make the code a little terser and easier to read:
function df2json(df)
io = IOBuffer()
write(io, "[\n")
write(io, join(map(row -> "{\"A\": $(row[:A]), \"B\": \"$(row[:B])\"}",
eachrow(d)), ",\n"))
write(io, "\n]\n")
json = takebuf_string(io)
close(io)
json
end
The keys here is to use the map and eachrow functions to get rid of the for
loops, and to build each item with string interpolation, which makes it
easier to see what the result will be.
Note that I end the entire message with a newline; I think this is good
practice in any string buffer protocol.
Next, I’d split the handling of the IO buffer away from the rest:
function df2json(df)
io = IOBuffer()
df2json(io, df)
json = takebuf_string(io)
close(io)
json
end
function df2json(io::IO, df)
write(io, "[\n")
write(io, join(map(row -> "{\"A\": $(row[:A]), \"B\": \"$(row[:B])\"}",
eachrow(d)), ",\n"))
write(io, "\n]\n")
end
I’d also make pretty-printing optional, to make it possible to write the
JSON as compact as possible too:
function df2json(df; pretty_print::Bool=false)
io = IOBuffer()
df2json(io, df; pretty_print=pretty_print)
json = takebuf_string(io)
close(io)
json
end
function df2json(io::IO, df; pretty_print::Bool=false)
write(io, "[")
pretty_print && write(io, "\n")
separator = "," * (pretty_print ? "\n\t" : "")
space = pretty_print ? " " : ""
write(io, join(map(row ->
"{\"A\":$space$(row[:A]),$space\"B\":$space\"$(row[:B])\"}", eachrow(d)),
separator))
pretty_print && write(io, "\n")
write(io, "]")
write(io, "\n")
end
Now, this allows you to print the message either for human reading:
julia> d = DataFrame(A=1:10, B=map(x -> x > 0.5 ? "F" : "M", rand(10)))
10x2 DataFrames.DataFrame
| Row | A | B |
|-----|----|-----|
| 1 | 1 | "M" |
| 2 | 2 | "M" |
| 3 | 3 | "M" |
| 4 | 4 | "M" |
| 5 | 5 | "F" |
| 6 | 6 | "F" |
| 7 | 7 | "F" |
| 8 | 8 | "M" |
| 9 | 9 | "F" |
| 10 | 10 | "F" |
julia> println(df2json(d; pretty_print=true));
[
{"A": 1, "B": "M"},
{"A": 2, "B": "M"},
{"A": 3, "B": "M"},
{"A": 4, "B": "M"},
{"A": 5, "B": "F"},
{"A": 6, "B": "F"},
{"A": 7, "B": "F"},
{"A": 8, "B": "M"},
{"A": 9, "B": "F"},
{"A": 10, "B": "F"}
]
or for minimizing network overhead:
julia> println(df2json(d))
[{"A":1,"B":"M"},{"A":2,"B":"M"},{"A":3,"B":"M"},{"A":4,"B":"M"},{"A":5,"B":"F"},{"A":6,"B":"F"},{"A":7,"B":"F"},{"A":8,
"B":"M"},{"A":9,"B":"F"},{"A":10,"B":"F"}]
// T
On Monday, November 9, 2015 at 6:12:31 AM UTC+1, Eric Forgy wrote:
This is embarrassing since I'm just learning, but in the interest of
> getting feedback and improving my Julia coding skills, here is what I did:
>
> function df2json(df::DataFrame)
>
> nrow,ncol = size(df)
>
> io = IOBuffer();
> write(io,"[\n")
> for irow = 1:nrow
> irow == nrow ? eor = "" : eor = ","
> write(io,"{")
> for icol = 1:ncol
> icol == ncol ? eoe = "" : eoe = ","
> sym = names(df)[icol]
> name = string(sym)
> if isa(value,Number)
> write(io,"\""*name*"\":"*string(df[irow,sym])*eoe)
> else
> write(io,"\""*name*"\":\""*df[irow,sym]*"\""*eoe)
> end
> end
> write(io,"}"*eor*"\n")
> end
> write(io,"]\n")
>
> json = takebuf_string(io)
> close(io)
> json
> end
>
>
> Any thoughts/suggestions? Thank you.
>