2016-06-09 83 views
-1

我在寻找不同的解决方案,包括那些被禁止使用的解决方案,以及那些我可以使用它们的所有优点的解决方案。如何合并2个文本文件

这是问题所在,我有两个文本文件,textFile1textFile2。他们每个人都包含排序的整数(这是最重要的条件),象下面显示:

textFile1  textFile2 
0    1 
2    3 
4    5 

我需要通过合并这两个文件来创建3文本文件,例如textFile3,以及预期的结果应该是:

textFile3 
0 
1 
2 
3 
4 
5 

我的第一个想法是通过线的两个文本文件的行复制成两个独立的阵列和比合并在新的两个排序阵列使用的解决方案,提供 in this question. 在那之后,我会复制这些成员的新数组放入textFile3,逐行。

你有什么建议吗?也许更好的方法?请在这里写下你的所有想法,他们每个人都会对我有所帮助。

+2

不能单纯使用合并排序合并的想法。 –

+0

结果序列是完整的还是可以有差距? – derape

+2

以及一些在堆栈溢出时合并两个数组的示例..它取决于文件的大小,如果这是可行的..它取决于你的编码器来确定哪一个是有效的..我们不会提供解决方案,只有编码协助才能解决问题。 – BugFinder

回答

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 
} 

唯一不同的是,获得下一个项目是不是仅仅增加一个数组索引更多地参与。

1

它们都是排序列表,为了避免内存消耗,请在这两个文件中打开一个阅读器。从两者中读取两行,比较前面,写入排序结果并根据每个文件的当前行采取行动。例如:将每个文件中的排序值作为指针处理,并继续比较并从较小的一边进行,直到完成。这将确保较小的内存占用量,对于较大的文件比较小的文件会更好。

您可以在网络上捏加算法here is oneanother that even mentions 0(1)。忽略它谈及数组的事实,你的文件是有效排序的数组,所以你不需要在内存中复制它。

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); 
}