patterncsharpModerate
Merging two files containing sorted numbers into one
Viewed 0 times
containingmergingintonumberstwofilesonesorted
Problem
The task is to merge 2 text files containing sorted integers into one file. Each number in both files is stored in new line(there are no empty lines,and only numbers are stored). Requirements are that if
My current solution is based on this algorithm:
The solution is working fine, I've tested it for different cases.But, I'm looking for you opinion and suggestions, how can I improve the code, since it is quite huge.
Also, can I avoid assigning value to
```
public static void Merge(string pathInputFile1, string pathInputFile2, string pathOutputFile)
{
int item1 = 0;
int item2 = 0;
bool endOfFile1 = false;
bool endOfFile2 = false;
string temp;
var inputFile1 = File.OpenText(pathInputFile1);
var inputFile2 = File.OpenText(pathInputFile2);
temp = inputFile1.ReadLine();
if (temp == null)
{
endOfFile1 = true;
}
else
{
item1 = Int32.Parse(temp);
}
temp = inputFile2.ReadLine();
if (temp == null)
{
endOfFile2 = true;
}
else
{
item2 = Int32.Parse(temp);
}
while (
file1 has n numbers and file2 has m numbers, running time must be O(n+m) and memory consumption O(1).My current solution is based on this algorithm:
while (not end of List A and not end of List B)
if (List A current item <= List B current item)
output List A current item
advance List A index
else
output List B current item
advance List B index
// At this point, one of the lists is empty.
// Output remaining items from the other
while (not end of List A)
output List A current item
advance List A index
while (not end of List B)
output List B current item
advance List B indexThe solution is working fine, I've tested it for different cases.But, I'm looking for you opinion and suggestions, how can I improve the code, since it is quite huge.
Also, can I avoid assigning value to
item 1 and item 2 variables at beginning? If I leave them unassigned, even if I pass them value visual studio is returning error saying that I'm using unassigned variables in while loop.```
public static void Merge(string pathInputFile1, string pathInputFile2, string pathOutputFile)
{
int item1 = 0;
int item2 = 0;
bool endOfFile1 = false;
bool endOfFile2 = false;
string temp;
var inputFile1 = File.OpenText(pathInputFile1);
var inputFile2 = File.OpenText(pathInputFile2);
temp = inputFile1.ReadLine();
if (temp == null)
{
endOfFile1 = true;
}
else
{
item1 = Int32.Parse(temp);
}
temp = inputFile2.ReadLine();
if (temp == null)
{
endOfFile2 = true;
}
else
{
item2 = Int32.Parse(temp);
}
while (
Solution
As the others have pointed out, there is a lot of repetition in your code.
This is however a great opportunity to threat the files as simple iterators from which you can extract integers. This is done using a simple C# generator.
Afterwards, simply follow the algorithm you initially described, but substitute
Abstracting further, you create a method which combines arbitrary iterators of sorted values:
Which leads you to a simple function that just iterates through something created from two stream readers and writer the result back:
This is however a great opportunity to threat the files as simple iterators from which you can extract integers. This is done using a simple C# generator.
IEnumerator ToIterator(StreamReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return Convert.ToInt32(line);
}
}Afterwards, simply follow the algorithm you initially described, but substitute
List with an iterator (IEnumerator in .NET terms):void MergeIntegersFiles(string source1, string source2, string destination)
{
using (var reader1 = new StreamReader(source1))
{
using (var reader2 = new StreamReader(source2))
{
using (var writer = new StreamWriter(destination))
{
var iterator1 = ToIterator(reader1);
var iterator2 = ToIterator(reader2);
var iterator1StillAvailable = iterator1.MoveNext();
var iterator2StillAvailable = iterator2.MoveNext();
while (iterator1StillAvailable && iterator2StillAvailable)
{
if (iterator1.Current <= iterator2.Current)
{
writer.WriteLine(iterator1.Current);
iterator1StillAvailable = iterator1.MoveNext();
}
else
{
writer.WriteLine(iterator2.Current);
iterator2StillAvailable = iterator2.MoveNext();
}
}
//check which iterator can still provide values
var iteratorRemaining = iterator1StillAvailable
? iterator1
: iterator2StillAvailable ? iterator2 : null;
if (null != iteratorRemaining)
{
do
{
writer.WriteLine(iteratorRemaining.Current);
} while (iteratorRemaining.MoveNext());
}
}
}
}
}Abstracting further, you create a method which combines arbitrary iterators of sorted values:
IEnumerable GetSortedValues(IEnumerator iterator1, IEnumerator iterator2) where T : IComparable
{
var iterator1StillAvailable = iterator1.MoveNext();
var iterator2StillAvailable = iterator2.MoveNext();
while (iterator1StillAvailable && iterator2StillAvailable)
{
if (iterator1.Current.CompareTo(iterator2.Current) < 1)
{
yield return iterator1.Current;
iterator1StillAvailable = iterator1.MoveNext();
}
else
{
yield return iterator2.Current;
iterator2StillAvailable = iterator2.MoveNext();
}
}
//check which iterator can still provide values
var iteratorRemaining = iterator1StillAvailable
? iterator1
: iterator2StillAvailable ? iterator2 : null;
if (null != iteratorRemaining)
{
do
{
yield return iteratorRemaining.Current;
} while (iteratorRemaining.MoveNext());
}
}Which leads you to a simple function that just iterates through something created from two stream readers and writer the result back:
void MergeIntegersFiles(string source1, string source2, string destination)
{
using (var reader1 = new StreamReader(source1))
{
using (var reader2 = new StreamReader(source2))
{
using (var writer = new StreamWriter(destination))
{
foreach (var value in GetSortedValues(ToIterator(reader1), ToIterator(reader2)))
{
writer.WriteLine(value);
}
}
}
}
}Code Snippets
IEnumerator<int> ToIterator(StreamReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return Convert.ToInt32(line);
}
}void MergeIntegersFiles(string source1, string source2, string destination)
{
using (var reader1 = new StreamReader(source1))
{
using (var reader2 = new StreamReader(source2))
{
using (var writer = new StreamWriter(destination))
{
var iterator1 = ToIterator(reader1);
var iterator2 = ToIterator(reader2);
var iterator1StillAvailable = iterator1.MoveNext();
var iterator2StillAvailable = iterator2.MoveNext();
while (iterator1StillAvailable && iterator2StillAvailable)
{
if (iterator1.Current <= iterator2.Current)
{
writer.WriteLine(iterator1.Current);
iterator1StillAvailable = iterator1.MoveNext();
}
else
{
writer.WriteLine(iterator2.Current);
iterator2StillAvailable = iterator2.MoveNext();
}
}
//check which iterator can still provide values
var iteratorRemaining = iterator1StillAvailable
? iterator1
: iterator2StillAvailable ? iterator2 : null;
if (null != iteratorRemaining)
{
do
{
writer.WriteLine(iteratorRemaining.Current);
} while (iteratorRemaining.MoveNext());
}
}
}
}
}IEnumerable<T> GetSortedValues<T>(IEnumerator<T> iterator1, IEnumerator<T> iterator2) where T : IComparable<T>
{
var iterator1StillAvailable = iterator1.MoveNext();
var iterator2StillAvailable = iterator2.MoveNext();
while (iterator1StillAvailable && iterator2StillAvailable)
{
if (iterator1.Current.CompareTo(iterator2.Current) < 1)
{
yield return iterator1.Current;
iterator1StillAvailable = iterator1.MoveNext();
}
else
{
yield return iterator2.Current;
iterator2StillAvailable = iterator2.MoveNext();
}
}
//check which iterator can still provide values
var iteratorRemaining = iterator1StillAvailable
? iterator1
: iterator2StillAvailable ? iterator2 : null;
if (null != iteratorRemaining)
{
do
{
yield return iteratorRemaining.Current;
} while (iteratorRemaining.MoveNext());
}
}void MergeIntegersFiles(string source1, string source2, string destination)
{
using (var reader1 = new StreamReader(source1))
{
using (var reader2 = new StreamReader(source2))
{
using (var writer = new StreamWriter(destination))
{
foreach (var value in GetSortedValues(ToIterator(reader1), ToIterator(reader2)))
{
writer.WriteLine(value);
}
}
}
}
}Context
StackExchange Code Review Q#131627, answer score: 10
Revisions (0)
No revisions yet.