Python-为每个给定密钥文件创建字典

Python-为每个给定密钥文件创建字典,python,file,dictionary,Python,File,Dictionary,我正在研究一个文本解析算法(开源端项目)。我非常感谢你的建议 我有一个以制表符分隔的txt文件,它按第一列(下面的示例数据集)排序。此列中存在重复条目。 最后,我想使用散列来指向所有具有相同键(第一列值)的值。如果出现一个新的密钥,哈希的内容将被序列化、保存等,然后清除,以便新的密钥填充它。因此,我的目标是只有一把钥匙在场。因此,如果我有N个唯一的键,我希望将N个散列分别指向它们各自的条目。尽管数据集的大小和内存堆都是GBs,但不会有多大帮助,因此我的推理是为每个键创建一个哈希,并分别处理每个键

我正在研究一个文本解析算法(开源端项目)。我非常感谢你的建议

我有一个以制表符分隔的txt文件,它按第一列(下面的示例数据集)排序。此列中存在重复条目。 最后,我想使用散列来指向所有具有相同键(第一列值)的值。如果出现一个新的密钥,哈希的内容将被序列化、保存等,然后清除,以便新的密钥填充它。因此,我的目标是只有一把钥匙在场。因此,如果我有N个唯一的键,我希望将N个散列分别指向它们各自的条目。尽管数据集的大小和内存堆都是GBs,但不会有多大帮助,因此我的推理是为每个键创建一个哈希,并分别处理每个键

样本数据集 A.23.4421 A-23.442 A.76.2224 B32.1232 B-23.001 C652.123 ... 因此,在上面的数据集片段中,我希望有一个“a”的散列(指向其各自的3倍项)。读取“B”时,序列化“A”哈希并清除哈希内容。对“B”重复此操作,直到数据集结束

我的伪代码如下:

declare hash for item in the dataset: key, value = item[0], item[1:] if key not in hash: if hash.size is 0: // pertains to the very first item hash.put(key, value) else: clear hash // if a new key is read but a diff. key is present. else: hash.put(key, value) // key already there so append it. 声明散列 对于数据集中的项: 键,值=项[0],项[1:] 如果密钥不在哈希中: 如果hash.size为0://则与第一项相关 hash.put(键、值) 其他: 清除哈希//如果读取了新密钥但存在差异密钥。 其他: hash.put(key,value)//key已经存在,所以要追加它。 如果有任何关于如何有效实现上述算法的建议,我将不胜感激。此外,如果我的散列推理/方法没有效率,或者可以提出改进,我将非常感谢。我的目标是最终创建内存散列,直到出现一个新的键

谢谢,

p、

您可以为第一列中的每个键打开anydbm(2.x)或dbm(3.x),以列的值命名。这是相当琐碎的——我不确定问题是什么

您还可以使用类似于我的cachedb模块的东西,让它判断某个东西是否是“新的”:我在两个项目中使用过它,都取得了很好的效果


无论采用哪种方式,您都可能会将键设置为由换行符或空值或其他内容分隔的ascii浮点列表。

您不会明确说明您提供的排序数据是否是典型的,或者同一个键是否可以在整个文件中与其他键交错,这确实会对算法产生根本性的影响。我从您的示例代码推断,它们将以任意顺序出现

你也没有说你打算把这样提取的数据放在哪里。这可能非常重要—有许多不同的方法来存储数据,应用程序可能是确定访问时间的关键功能。因此,您可能需要考虑各种不同存储类型的使用。在不知道您打算如何使用结果结构的情况下,以下建议可能不合适

因为数据是浮点数字,所以您可能需要考虑使用以保持简单的浮点数的列表,这些浮点数是针对字母表的。这样做的优点是,所有进出外部存储器的酸洗和解酸洗都是自动处理的。如果需要增加速度,请考虑使用更有效的酸洗协议(未使用的参数之一为代码> Selv.On()/<代码>。 您可能想知道为什么我不在已经看到密钥的情况下使用

shelf[k].append(v)
。这是因为只有键分配的操作才会触发值更改的检测。您可以阅读shelve模块文档以了解更多详细信息,并了解如何使用二进制pickle格式


还请注意,由于
shelve.open()
的“c”参数,此程序每次运行时都会重新创建shelf,请使用itertools.groupby,将文件作为迭代器传递给它:

from itertools import groupby
from cStringIO import StringIO

sourcedata = StringIO("""\
A    ...    23.4421
A    ...   -23.442
A    ...    76.2224
B    ...    32.1232
B    ...    -23.001
C    ...    652.123""")

# or sourcedata = open("zillion_gigabyte_file.dat")

for key,lines in groupby(sourcedata, key=lambda s:s.split()[0]):
    accum = [float(s.split()[2]) for s in lines]
    print key, accum

groupby非常聪明和高效,一次只在内存中保存很少的数据,直到最后一刻才以迭代器的形式保存内容。在groupby中,您描述的是散列,一次只在内存中保留一个,所有这些都已经为您完成了。

不清楚您的问题是什么。看起来您只是想将具有相同键的值分组在一起。由于键已经被排序,一个列表就足够了,不需要散列。
# Transform the data:
# note it's actually more efficient to process line-by-line
# as you read it from a file - obviously it's best to try
# to avoid reading the whole data set into memory at once.
data = """\
A    ...    23.4421
A    ...   -23.442
A    ...    76.2224
B    ...    32.1232
B    ...    -23.001
C    ...    652.123"""

data = [(k, float(v))
          for (k, _, v) in
          [_.split() for _ in data.splitlines()]]

# create a shelve
import shelve
shelf = shelve.open("myshelf", "c")

# process data
for (k, v) in data:
    if k in shelf:
        # see note below for rationale
        tmp = shelf[k]
        tmp.append(v)
        shelf[k] = tmp
    else:
        shelf[k] = [v]

# verify results
for k in shelf.keys():
    print k, shelf[k]
from itertools import groupby
from cStringIO import StringIO

sourcedata = StringIO("""\
A    ...    23.4421
A    ...   -23.442
A    ...    76.2224
B    ...    32.1232
B    ...    -23.001
C    ...    652.123""")

# or sourcedata = open("zillion_gigabyte_file.dat")

for key,lines in groupby(sourcedata, key=lambda s:s.split()[0]):
    accum = [float(s.split()[2]) for s in lines]
    print key, accum