Python 比较两种词典的效率

Python 比较两种词典的效率,python,dictionary,Python,Dictionary,以下程序已在两个文件(txt,~10MB ea.)上运行了约22小时。每个文件大约有10万行。有人能告诉我我的代码效率有多低,也许是一种更快的方法。输入指令是有序的,必须保持顺序: import collections def uniq(input): output = [] for x in input: if x not in output: output.append(x) return output Su = {} with open ('Sucros

以下程序已在两个文件(txt,~10MB ea.)上运行了约22小时。每个文件大约有10万行。有人能告诉我我的代码效率有多低,也许是一种更快的方法。输入指令是有序的,必须保持顺序:

import collections

def uniq(input):
  output = []
  for x in input:
    if x not in output:
      output.append(x)
  return output

Su = {}
with open ('Sucrose_rivacombined.txt') as f:
    for line in f:
        (key, val) = line.split('\t')
        Su[(key)] = val
    Su_OD = collections.OrderedDict(Su)

Su_keys = Su_OD.keys()
Et = {}

with open ('Ethanol_rivacombined.txt') as g:
    for line in g:
        (key, val) = line.split('\t')
        Et[(key)] = val
    Et_OD = collections.OrderedDict(Et)

Et_keys = Et_OD.keys()

merged_keys = Su_keys + Et_keys
merged_keys =  uniq(merged_keys)

d3=collections.OrderedDict()

output_doc = open("compare.txt","w+")

for chr_local in merged_keys:
    line_output = chr_local
    if (Et.has_key(chr_local)):
        line_output = line_output + "\t" + Et[chr_local]
    else:
        line_output = line_output + "\t" + "ND"
    if (Su.has_key(chr_local)):
        line_output = line_output + "\t" + Su[chr_local]
    else:
        line_output = line_output + "\t" + "ND"

    output_doc.write(line_output + "\n")
输入文件如下:并非所有键都存在于两个文件中

Su:
chr1:3266359    80.64516129
chr1:3409983    100
chr1:3837894    75.70093458
chr1:3967565    100
chr1:3977957    100


Et:
chr1:3266359    95
chr1:3456683    78
chr1:3837894    54.93395855
chr1:3967565    100
chr1:3976722    23
我希望输出如下所示:

chr1:3266359    80.645    95
chr1:3456683    ND        78

uniq
替换为此,因为输入是可散列的:

def uniq(input):
  output = []
  s = set()
  for x in input:
    if x not in s:
      output.append(x)
      s.add(x)
  return output

这将把一个几乎
O(n^2)
过程减少到几乎
O(n)
替换
uniq
,因为输入是可散列的:

def uniq(input):
  output = []
  s = set()
  for x in input:
    if x not in s:
      output.append(x)
      s.add(x)
  return output

这将把一个几乎
O(n^2)
的过程减少到几乎
O(n)
您的
输出是一个列表,但您的输入是字典:它们的键保证是唯一的,但是您的
不在输出中
需要与列表中的每个元素进行比较,这是组合的。(您正在进行n^2次比较,因为这是
而不是
检查。)

您可能完全可以用以下内容取代uniq:

Su_OD.update(Et_OD)
这对我很有用:

from collections import OrderedDict

one = OrderedDict()
two = OrderedDict()

one['hello'] = 'one'
one['world'] = 'one'

two['world'] = 'two'
two['cats'] = 'two'

one.update(two)

for k, v in one.iteritems():
    print k, v
输出:

    hello one
    world two
    cats two

您的
output
是一个列表,但您的输入是字典:它们的键保证是唯一的,但是您的
not in output
需要与列表中的每个元素进行比较,这是组合的。(您正在进行n^2次比较,因为这是
而不是
检查。)

您可能完全可以用以下内容取代uniq:

Su_OD.update(Et_OD)
这对我很有用:

from collections import OrderedDict

one = OrderedDict()
two = OrderedDict()

one['hello'] = 'one'
one['world'] = 'one'

two['world'] = 'two'
two['cats'] = 'two'

one.update(two)

for k, v in one.iteritems():
    print k, v
输出:

    hello one
    world two
    cats two

您不需要独特的功能。

伪代码,如:

  • 按顺序读取文件2
  • 进程文件1写出其项目(已正确订购)
  • pop,使用文件2中的defalut作为输出行的最后一部分
  • 在文件1被使用后,处理文件2中的已排序dict
  • 此外,爱列表理解…您可以通过以下方式读取文件:

    OrderedDict(line.strip().split('\t') for line in open('Ethanol_rivacombined.txt'))
    
    只有一个有序的dict和“successour\u rivacombined.txt”甚至从未进入内存。应该是超快的

    编辑完整代码(不确定输出行格式)


    您不需要独特的功能。

    伪代码,如:

  • 按顺序读取文件2
  • 进程文件1写出其项目(已正确订购)
  • pop,使用文件2中的defalut作为输出行的最后一部分
  • 在文件1被使用后,处理文件2中的已排序dict
  • 此外,爱列表理解…您可以通过以下方式读取文件:

    OrderedDict(line.strip().split('\t') for line in open('Ethanol_rivacombined.txt'))
    
    只有一个有序的dict和“successour\u rivacombined.txt”甚至从未进入内存。应该是超快的

    编辑完整代码(不确定输出行格式)



    为什么不在较小的输入上对其进行分析,自己看看时间花在了哪里?我不知道该怎么做。我早些时候在一半大小的文件上运行了它,只花了大约3个小时。CPU使用率为25%,RAM仅为1.6GB左右,还有约6GB的空闲空间,因此不像其紧张的资源。我只是想知道我是否编错了代码,导致它继续不必要地读取文件。您是否验证了这是否符合您的要求?因为
    Su
    是一个普通的dict,所以当您将其转换为
    Su\u OD
    时,文件系统顺序已经丢失。您可能想要预先创建有序的dict?在“for”部分下面是否缺少一些缩进,以确保if-else通过循环?您可以考虑直接写入而不是每次构造Lynl输出,而不是重复级联字符串。哦,你也可以考虑CSV模块用于你的TSV输出。@ JoBrand:我的意思是使用一个自动工具来告诉你时间在哪里。请参阅(为了获得最佳结果,您可能需要对代码进行一点重构。)为什么不在较小的输入上对其进行分析,并亲自查看时间花在了哪里?我不知道如何做到这一点。我早些时候在一半大小的文件上运行了它,只花了大约3个小时。CPU使用率为25%,RAM仅为1.6GB左右,还有约6GB的空闲空间,因此不像其紧张的资源。我只是想知道我是否编错了代码,导致它继续不必要地读取文件。您是否验证了这是否符合您的要求?因为
    Su
    是一个普通的dict,所以当您将其转换为
    Su\u OD
    时,文件系统顺序已经丢失。您可能想要预先创建有序的dict?在“for”部分下面是否缺少一些缩进,以确保if-else通过循环?您可以考虑直接写入而不是每次构造Lynl输出,而不是重复级联字符串。哦,你也可以考虑CSV模块用于你的TSV输出。@ JoBrand:我的意思是使用一个自动工具来告诉你时间在哪里。请参阅(为了获得最佳结果,您可能需要对代码进行一些重构。)非常感谢!它现在运行约8秒。您为什么保留输出,或者为什么还要检查每个元素是否在集合中?为什么不干脆做
    s=set(Su_OD.keys());s、 更新(Et_OD.keys())
    @KurzedMetal以保留OP想要的元素顺序。非常感谢!它现在运行约8秒。您为什么保留输出,或者为什么还要检查每个元素是否在集合中?为什么不干脆做
    s=set(Su_OD.keys());s、 更新(Et_OD.keys())
    @KurzedMetal以保留OP想要的元素顺序。谢谢。这是很好的和紧凑的,对于超过500k行的数据集,它的工作速度非常快。谢谢。这是很好的和紧凑的,对于超过500k行的数据集工作速度非常快。使用
    Su_OD.update(Et_OD)
    将不起作用,因为
    Su_OD
    Et_OD
    中可能存在相同的键,并且该表达式将使用
    Et_OD
    中的值覆盖
    Su_OD
    中的键,从而丢失OP wan中的数据值