Python 从一个巨大的文本文件中列出前5个大数字的最佳方法

Python 从一个巨大的文本文件中列出前5个大数字的最佳方法,python,file,heap,top-n,Python,File,Heap,Top N,试图找到从150G文本文件中列出前5位数字的最佳简单方法 我搜索的文件在每行中只有数字,如下所示 456789876 098765 36 48987 4509876 . . . 尝试了下面的程序,但仍然只显示数字中的第一个数字,而不是完整的数字 from heapq import nlargest data=open('number.txt','r') text=data.read() print (text) print nlargest(5, (text)) data.close()

试图找到从150G文本文件中列出前5位数字的最佳简单方法

我搜索的文件在每行中只有数字,如下所示

456789876
098765
36
48987
4509876
.
.
.
尝试了下面的程序,但仍然只显示数字中的第一个数字,而不是完整的数字

from heapq import nlargest

data=open('number.txt','r')
text=data.read()
print (text)
print nlargest(5, (text))
data.close()

有没有其他方法来选择前五名?

您没有将数据视为数字。而是将整个文件内容(一个非常大的字符串)传递给
nlargest()
,它只能按字典顺序提供最后的字符。在本例中,字符
'9'
排序在字符
'8'
之后

您需要a)逐行读取输入,而不是作为一个大字符串;b)将数据转换为整数,以便通过数值进行比较:

from heapq import nlargest

def as_numbers(it):
    for line in it:
        try:
            yield int(line)
        except ValueError:
            # not a line with a number, skip
            continue

with open('number.txt') as data:
    five_largest = nlargest(5, as_numbers(data))                
    print(five_largest)
我在这里使用了一个生成器函数将行转换为整数,因为这样可以更容易地继续使用
heapq.nlargest()
(这绝对是用于此作业的正确工具,因为它可以有效地保持O(NlogK)中的top-n值可用)时间,因此对于固定的K=5项,基本上是线性的,并且只与文件中的整数值成比例)。生成器函数负责转换为
int()
,跳过任何无法转换的行

还要注意对打开的文件对象使用
with
;在
with
块的末尾,文件将自动关闭,无需在此显式调用
data.close()
。即使有例外,这也会发生

演示:


您没有将数据视为数字。而是将整个文件内容(一个非常大的字符串)传递给
nlargest()
,它只能按字典顺序提供最后的字符。在本例中,字符
'9'
排序在字符
'8'
之后

您需要a)逐行读取输入,而不是作为一个大字符串;b)将数据转换为整数,以便通过数值进行比较:

from heapq import nlargest

def as_numbers(it):
    for line in it:
        try:
            yield int(line)
        except ValueError:
            # not a line with a number, skip
            continue

with open('number.txt') as data:
    five_largest = nlargest(5, as_numbers(data))                
    print(five_largest)
我在这里使用了一个生成器函数将行转换为整数,因为这样可以更容易地继续使用
heapq.nlargest()
(这绝对是用于此作业的正确工具,因为它可以有效地保持O(NlogK)中的top-n值可用)时间,因此对于固定的K=5项,基本上是线性的,并且只与文件中的整数值成比例)。生成器函数负责转换为
int()
,跳过任何无法转换的行

还要注意对打开的文件对象使用
with
;在
with
块的末尾,文件将自动关闭,无需在此显式调用
data.close()
。即使有例外,这也会发生

演示:

输入:

代码:

结果:

[235423, 563456, 4509876, 47345734, 456789876]
[3, 36, 656, 6234, 7348]
输入:

代码:

结果:

[235423, 563456, 4509876, 47345734, 456789876]
[3, 36, 656, 6234, 7348]

您没有将数据视为数字。您有字符串,并且这些字符串是按字典顺序排序的,因此“最大”数字可以是
'9'
,因为
'9'
'888888'
之前进行排序。您还向
nlargest()提供了一个字符串,因此,它将处理单个字符,为您提供一系列
'9'
字符。您没有将数据视为数字。您有字符串,并且这些字符串是按字典顺序排序的,因此“最大”数字可以是
'9'
,因为
'9'
'888888'
之前进行排序。您还向
nlargest()提供了一个字符串,因此,它将处理单个字符,给您一系列
'9'
字符。我对
heapq
一点都不熟悉,但如果它需要任何iterable,那么我同意这是正确的方法(它可能只需要一个列表,需要您将整个文件读入内存!)@JoeIddon:
heapq.nlargest()
接受一个iterable,并且一个包含5个元素的列表(堆)通过使用保持最新。堆不需要完全排序(堆顺序不是完全排序的顺序,但可以在末尾进行有效排序)。@JoeIddon:每当需要选择序列中的前N个或最少N个时,请使用
heapq
Counter.most_common()
会在您请求计数器子集时执行,例如。我对
heapq
一点都不熟悉,但如果它需要任何iterable,那么我同意这是正确的方法(它可能只需要一个列表,需要您将整个文件读入内存!)@JoeIddon:
heapq.nlargest()
接受一个iterable,并且一个包含5个元素的列表(堆)通过使用保持最新。堆不需要完全排序(堆顺序不是完全排序的顺序,但可以在末尾进行有效排序)。@JoeIddon:每当需要选择序列中的前N个或最少N个时,请使用
heapq
<代码>计数器。例如,每当您要求计数器的子集时,most_common()
都会这样做。这是非常低效的,原因有两个:a)您将整个文件读入内存,因此现在需要千兆字节的工作内存;b)对整个列表进行排序只是为了找到前5个或至少5个,这是对处理时间的巨大浪费。您永远不需要知道元素的确切顺序(不在两端),只要它们不是这些子集的一部分即可。OP已经为此任务使用了效率更高的
heapq
模块,排序需要O(NlogN)时间,而heapq需要O(NlogK)时间。对于100万个元素,这是8倍长的一个因素!此外,使用
heapq.nlargest()
只需要在任何时候将运行中的前5个元素保存在内存中,您会发现使用排序的速度会更慢,因为操作系统必须在内存中交换您的版本,而不是在heapq情况下仅处理缓冲和少量整数,因此,总内存大小将主要由Python本身占用,而不是一个系统中150GB的数字
[235423, 563456, 4509876, 47345734, 456789876]
[3, 36, 656, 6234, 7348]