如何解决将n个“words”文件8个随机字母按字典顺序排序,放到一个output.txt文件中
我得到了 n 个文件,例如 3 个文件,大约有 400000 个单词,由八个“随机”字母组成,例如。 aaabcdfe
。每个文件都按字典顺序排列,我应该按照排序和字典顺序将所有文件合并到一个输出文件中(无重复)。
我知道如何将它们从文件中获取到数组,反之亦然。我的主要问题是空间(大约 32MB)。我正在尝试将文件分成小块(可能是 60000 个单词,每个文件 20k,然后将它们合并在一起),但我真的不确定如何去做。想象一下,我有一个大约 30k 字的数组,我可以从那里去哪里?我应该把它们放在一个新文件还是输出文件中。我应该将它们合并在一起而不使用数组吗?另一个问题是我只能将一个文件写入输出,因为如果我先写入一个文件,然后再写入另一个文件,第二个文件会覆盖所有第一个文件,现在输出中只剩下第二个文件。我想过优先队列,但到目前为止还没有取得任何进展。
我还在学习,因为这对我来说是全新的,如果这有点小菜,很抱歉。只是在此类事情上寻求有经验的人的提示。
解决方法
对于现代计算机来说,现在 100-200MB 的数据并不多,因此在许多情况下,文件合并和 Array.Sort() 可能会为您解决问题。
但是,如果条目或文件的数量急剧增加,也许您可以选择更安全的算法,例如,通过按首字母对条目进行分组。您可以将所有文件中以“A”或“a”开头的所有单词加载到列表中,然后对列表进行排序(yourList.Sort()
),然后将其写入输出文件。然后,再选择字母“B”/“b”,依此类推。
通过按第一个字母(或前 2 个字母,如果需要)分组,您可以确保在任何时候完成的排序不会被后续条目加载修改。
编辑。在伪代码中它会是这样的:
char[] myLetters = ['a','b','c','d',...];
// open a read connection to all involved files and store its read pointer in and array called myLetters
// create a file and open a write connection
outputFile = File.Open(filename,"Write");
foreach(char lett in myLetters)
{
List myCurrentLetterEntriesList = new List();
foreach(File f in allMyFiles)
{
string Entry = f.ReadLine();
while(Entry.FirstLetter == lett )
{
myCurrentLetterEntriesList .Add( Entry );
Entry = f.ReadLine();
}
f.Seek(-1,CurrentPosition); //to start in the last entry that was discarded
}
myCurrentLetterEntriesList.Sort();
string previousEntry = myCurrentLetterEntriesList[0]
outputFile.WriteLine(previousEntry);
for i=1:myCurrentLetterEntriesList.count-1
{
string entry = myCurrentLetterEntriesList[i];
if(entry!=previousEntry )
{
outputFile.WriteLine(entry);
previousEntry=entry;
}
}
}
//Close connections to input and output files
,
(I'm really not sure on how to do it
,where do I go from there?
这更多是程序开发方法和实践的问题(Software Engineering Stack Exchange 的主题 - 堆栈上的主题溢出)和问题解决(不是我所知道的任何 SE 网站的主要主题)。
答案有帮助/正确的变化 - 1960 年代的真实情况不一定会延续到当前的千禧年,或今天的智慧到 2050 年:
学习问题和相应答案在生活中的用处不如备考。
-
My main problem is the space (around 32MB)
你怎么知道的?
32 MB 是 2020 年计算服务器处理器的“最远级缓存”的数量级。
400000 个 8 个字母的单词更有可能出现在大约 3.2 MB 的文件中(是 400000 个单词total 还是 每个文件?)。
在许多现代运行时环境中,每个字符在内存中占用两个字节 - 即使是 3*400000*8 个字符,也不足 20 MB(如果一次转换/存储许多/所有单词,“每个单词的开销”可能加起来:测量)。
虽然我认为在旅途中尝试发现可能的问题很有用:
开始简单。测试按预期工作。 测量。 -
divide the files into [say 20 chunks each…merge them together…Imagine…] an array sorted as [specified]
刚刚做了:你怎么知道文件 2 中 next(未读)块的最后一个单词不需要在文件 1 中的第一个之前?
作为一种极端情况,想象任何一个文件中的所有单词都以相同的字母开头,在所有文件中都是独一无二的,例如'n'
、'o'
、't'
。
对“这个”问题的传统回答似乎是
- 构建一个优先队列PQ,其中包含来自每个序列的一个记录,并指示它来自哪个序列
- 虽然 PQ 不为空
- 将 PQ 中最高优先级的记录 R 替换为相同序列中的下一条记录(如果有),否则只需提取 R
- 输出R,偏离“标准问题和解决方案”:如果不等于之前的输出
(或者避免在 PQ 中插入重复项)
-我不一定买。
我希望我能衡量一下“微不足道的方法”:阅读整个shebang并对其进行标准排序不行,接下来使用上面的方法。
如果两者都没有削减它,我应该寻找“其他”“明显”的改进,例如尝试将八个字母的词作为64位机器词处理.
失败了,我可能会尝试分批读取文件,将 PQ 保持在 已经从每个文件中读取的最后/最低优先级单词/记录的上面,并愉快地处理记录,直到输出一个等于来自 PQ 的最高优先级记录,从它的文件中读取另一个批次。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。