30 lines
870 B
Plaintext
30 lines
870 B
Plaintext
defmodule StreamMerge do
|
|
def merge2(file1, file2), do: mergeN([file1, file2])
|
|
|
|
def mergeN(files) do
|
|
Enum.map(files, fn fname -> File.open!(fname) end)
|
|
|> Enum.map(fn fd -> {fd, IO.read(fd, :line)} end)
|
|
|> merge_loop
|
|
end
|
|
|
|
defp merge_loop([]), do: :ok
|
|
defp merge_loop(fdata) do
|
|
{fd, min} = Enum.min_by(fdata, fn {_,head} -> head end)
|
|
IO.write min
|
|
case IO.read(fd, :line) do
|
|
:eof -> File.close(fd)
|
|
List.delete(fdata, {fd, min}) |> merge_loop
|
|
head -> List.keyreplace(fdata, fd, 0, {fd, head}) |> merge_loop
|
|
end
|
|
end
|
|
end
|
|
|
|
filenames = ~w[temp1.dat temp2.dat temp3.dat]
|
|
Enum.each(filenames, fn fname ->
|
|
IO.puts "#{fname}: " <> File.read!(fname) |> String.replace("\n", " ")
|
|
end)
|
|
IO.puts "\n2-stream merge:"
|
|
StreamMerge.merge2("temp1.dat", "temp2.dat")
|
|
IO.puts "\nN-stream merge:"
|
|
StreamMerge.mergeN(filenames)
|