我正在寻找不同的解决方案,包括那些禁止使用.NET libraries
的解决方案以及我可以利用它们的所有优点的解决方案。
问题是,我有两个文本文件textFile1
和textFile2
。它们中的每一个都包含有序整数(这是最重要的条件),如下所示:
textFile1 textFile2
0 1
2 3
4 5
我需要通过合并这两个文件来创建第三个文本文件,例如textFile3
,预期结果应为:
textFile3
0
1
2
3
4
5
我的第一个想法是将这两个文本文件逐行复制到两个单独的数组中,而不是使用解决方案将两个已排序的数组合并到新的数组中
in this question.
之后,我将逐行将这些新数组的成员复制到textFile3
。
你有什么建议吗?也许更好的方法?请在这里写下您的所有想法,每个想法对我都有帮助。
答案 0 :(得分:2)
合并两个有序序列很容易推广并实现为扩展方法,如下所示:
public static class Algorithms
{
public static IEnumerable<T> MergeOrdered<T>(this IEnumerable<T> seq1, IEnumerable<T> seq2, IComparer<T> comparer = null)
{
if (comparer == null) comparer = Comparer<T>.Default;
using (var e1 = seq1.GetEnumerator())
using (var e2 = seq2.GetEnumerator())
{
bool more1 = e1.MoveNext(), more2 = e2.MoveNext();
while (more1 && more2)
{
int compare = comparer.Compare(e1.Current, e2.Current);
yield return compare < 0 ? e1.Current : e2.Current;
if (compare <= 0) more1 = e1.MoveNext();
if (compare >= 0) more2 = e2.MoveNext();
}
for (; more1; more1 = e1.MoveNext())
yield return e1.Current;
for (; more2; more2 = e2.MoveNext())
yield return e2.Current;
}
}
}
然后可以通过以下方式完成具体任务:
static void Merge(string inputFile1, string inputFile2, string outputFile)
{
Func<string, IEnumerable<KeyValuePair<int, string>>> readLines = file =>
File.ReadLines(file).Select(line =>
new KeyValuePair<int, string>(int.Parse(line), line));
var inputLines1 = readLines(inputFile1);
var inputLines2 = readLines(inputFile2);
var comparer = Comparer<KeyValuePair<int, string>>.Create(
(a, b) => a.Key.CompareTo(b.Key));
var outputLines = inputLines1.MergeOrdered(inputLines2, comparer)
.Select(item => item.Value);
File.WriteAllLines(outputFile, outputLines);
}
答案 1 :(得分:1)
它们都是排序列表并且为了避免内存消耗,打开两个文件的阅读器。从两者中读取两行,进行比较,编写已排序的结果,并根据每个文件的当前行执行操作。例如:将每个文件中的排序值视为指针,并从较小的一侧继续比较和推进直至完成。这将确保较小的内存占用空间,对于较大的文件而言比较小的文件更好。
您可以通过网络捏合算法here is one和another that even mentions 0(1)。忽略它谈论数组的事实,你的文件是有效排序的数组,所以你不需要在内存中复制它。
答案 2 :(得分:1)
合并两个文件是合并两个数组的一个相当简单的修改。我们的想法是用读取文件的下一行来替换数组索引增量。例如,我在博客(http://blog.mischel.com/2014/10/24/merging-sorted-sequences/)中显示的标准合并算法是:
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 index
要制作合并文件,首先要打开并阅读每个文件的第一行。但是,它有点棘手,因为你必须检查文件的结尾。 “获取下一行”有点......奇怪。
int item1;
int item2;
bool eof1 = false;
bool eof2 = false;
string temp;
var file1 = File.OpenText(textFile1);
temp = file1.ReadLine();
if (temp == null)
eof1 = true;
else
item1 = int.Parse(temp);
// do the same thing for file2
然后我们可以进行标准合并:
while (!eof1 && !eof2)
{
if (item1 <= item2)
{
outputFile.WriteLine(item1);
// get next item from file1
temp = file1.ReadLine();
if (temp == null)
eof1 = true;
else
item1 = int.Parse(temp);
}
else
{
// output item2 and get next line from file2
}
}
// and the cleanup
while (!eof1)
{
// output item1, and get next line from file1
}
while (!eof2)
{
// output item2, and get next file from file2
}
唯一不同的是,获取下一个项目比仅增加数组索引更为复杂。