Stream merge: Difference between revisions

Content added Content deleted
Line 1,474: Line 1,474:
</pre>
</pre>
=={{header|Nim}}==
=={{header|Nim}}==
===Merge two streams===
optimized for clarity and simplicity, not performance.
Optimized for clarity and simplicity, not performance.
assumes two files containing sorted integers separated by newlines
assumes two files containing sorted integers separated by newlines
<lang nim>import streams,strutils
<lang nim>import streams,strutils
Line 1,487: Line 1,488:
for line in stream2.lines:
for line in stream2.lines:
echo line</lang>
echo line</lang>

===Merge N streams===
{{trans|Phix}}
Of course, as Phix and Nim are very different languages, the code is quite different, but as Phix, we use a priority queue (which is provided by the standard module <code>heapqueue</code>. We work with files built from the “Data” constant, but we destroy them after usage. We have also put the whole merging code in an procedure.

<lang Nim>import heapqueue, os, sequtils, streams

type
Source = tuple[stream: Stream; line: string]
SourceHeap = HeapQueue[Source]


# Comparison of sources. Needed for the heap to sort the sources by line contents.
proc `<`(a, b: Source): bool = a.line < b.line


proc add(heap: var SourceHeap; stream: Stream) =
## Add a stream to the heap.
if stream.atEnd:
stream.close()
else:
heap.push((stream, stream.readLine()))


proc merge(inStreams: seq[Stream]; outStream: Stream) =
## Merge the input streams into an output stream.

# Initialize the heap.
var heap: SourceHeap
for stream in inStreams:
heap.add(stream)

# Merging loop.
while heap.len > 0:
let (stream, line) = heap.pop()
outStream.writeLine line
heap.add(stream)


when isMainModule:

const
Data = ["Line 001\nLine 008\nLine 017\n",
"Line 019\nLine 033\nLine 044\nLine 055\n",
"Line 019\nLine 029\nLine 039\n",
"Line 023\nLine 030\n"]
Filenames = ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]

# Create files.
for i, name in Filenames:
writeFile(name, Data[i])

# Create input and output streams.
let inStreams = Filenames.mapIt(Stream(newFileStream(it)))
let outStream = Stream(newFileStream(stdout))

# Merge the streams.
merge(inStreams, outStream)

# Clean-up: delete the files.
for name in Filenames:
removeFile(name)</lang>

{{out}}
<pre>Line 001
Line 008
Line 017
Line 019
Line 019
Line 023
Line 029
Line 030
Line 033
Line 039
Line 044
Line 055</pre>


=={{header|Perl}}==
=={{header|Perl}}==