Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有效存储的字典。这个数据结构存在吗?它叫什么?_Python_Data Structures_Bioinformatics - Fatal编程技术网

Python 有效存储的字典。这个数据结构存在吗?它叫什么?

Python 有效存储的字典。这个数据结构存在吗?它叫什么?,python,data-structures,bioinformatics,Python,Data Structures,Bioinformatics,我想要一个数据结构,它存储了大量的低熵数据,这些数据通常彼此相似。我想高效地存储它们(以某种方式压缩),并通过索引或匹配检索它们。快速检索比压缩更重要,但它不是存储未压缩数据的选项 我能想到的最好的例子是存储从大量文本中提取的10亿个书面句子(以压缩形式存储在磁盘上) 如果两个句子相同,它们应该有相同的索引 我想通过索引或通配符匹配来检索它们(regex也不错,但不是必需的)。即: 我可以压缩每个句子,但这忽略了一个事实,即许多条目是相似的 我可以将它们分类并存储差异。但是添加和删除元素是非常困

我想要一个数据结构,它存储了大量的低熵数据,这些数据通常彼此相似。我想高效地存储它们(以某种方式压缩),并通过索引或匹配检索它们。快速检索比压缩更重要,但它不是存储未压缩数据的选项

我能想到的最好的例子是存储从大量文本中提取的10亿个书面句子(以压缩形式存储在磁盘上)

如果两个句子相同,它们应该有相同的索引

我想通过索引或通配符匹配来检索它们(regex也不错,但不是必需的)。即:

我可以压缩每个句子,但这忽略了一个事实,即许多条目是相似的

我可以将它们分类并存储差异。但是添加和删除元素是非常困难的

它应该支持unicode

我确信有某种树结构可以做到这一点

如果它有python包装器,则会获得额外的积分

这看起来非常接近,但自2002/py2.2以来就没有看到任何动作,我无法让它运行。如果有更新/更好的选择,我很想听听


我之所以加入生物信息学标签,是因为我知道这里使用了后缀树和类似的数据结构。

您的问题听起来与a的用例完全相同,a是一种基于树的数据结构,通过前缀存储字符串。我自己还没有使用过这些实现,但是快速搜索一下Google代码,就会发现开源的trie项目和。前两个是java,第三个是C++。我希望在Python上写一个围绕C++的包装比在java上写包装更容易,因为Python具有与C.</P>互操作的内置能力。 编辑

我已经检查了GitHub,并且在Python实现方面取得了一些成功。我找到了pythontrie实现和


然而,如果你真的要处理10亿个句子,即使是一个写得非常好的纯Python实现(这三个都是)也可能会耗尽内存。

正如你已经指出的,后缀树或基数树可能是最好的选择。我建议:

  • 创建一个文件,将ID存储在叶子中。首先查看链接,但我相信你必须对找到的内容进行微调,以满足你的需要

  • 创建将ID映射到树中路径的dict。这将允许您通过id快速检索句子(找到路径,按照路径装入句子)。请注意,这将使插入和删除的成本有点高:每次更改非叶节点时,每个子代都需要在dict中更新其路径

    2.1。另一种方法(如果路径太长)是让每个节点存储对其父节点的引用,因此dict只需要引用叶节点。我相信大多数实现都不会这样做,因为尝试的主要目标是加速查找,而不是压缩文本本身

  • 通配符搜索有点棘手,这取决于您需求的复杂性。提供的示例很简单:跟随前缀的节点,直到找到通配符,然后返回所有子体。在这种情况下,一般的trie可能比更专业的基数树更容易处理,但对空间的要求更高

  • 顺便说一下,您还可以优化基数trie以占用更少的空间,方法是使用一些间接方法,将字符串插入节点中,并为长的公共子字符串添加额外的节点。例如:

    unique_strings = [ # Not a real array, just an hypothetical "intern table"
        "The quick ",
        "brown fox ",
        "green frog ",
        "jumps over the lazy ",
        "dog.",
        "fox.",
        "frog.",
    ]
    radix_trie = (0, {        # The quick *
        "b":(1, {             # The quick brown fox *
            "j":(3, {         # The quick brown fox jumps over the lazy *
                "d":(4,{},1), # The quick brown fox jumps over the lazy dog.
                "f":(6,{},3), # The quick brown fox jumps over the lazy frog.
            }),
        }),
        "g":(2, {             # The quick green frog *
            "j":(3, {         # The quick green frog jumps over the lazy *
                "f":(5,{},2), # The quick green frog jumps over the lazy fox.
            }),
        }),
    })
    # The nodes ("b", "j") and ("g", "j") wouldn't occur in a regular radix tree,
    # since they have no siblings. Adding them, however, gives a net gain of space.
    #
    # "jumps over the lazy " is a common substring of
    #     "brown fox jumps over the lazy " and
    #     "green frog jumps over the lazy fox."
    # which would occur naturally in a radix tree with only the 3 sentences given.
    paths = {
        1:("b", "j", "d"),
        2:("g", "j", "f"),
        3:("b", "j", "f"),
    }
    
    当然,对于您的示例来说,这很容易设置,但是在“野外”中查找重复的子字符串将有点困难。(在任何一对字符串中查找长的公共子字符串:非常昂贵的操作是可行的,请参见更新)但是,假设插入/删除是一个不频繁的操作,这应该不是一个大问题

    注意:我建议使用基数树而不是trie,因为前者的空间需求要小得多


    更新:如果你打算自己解决这个问题,这里还有一个使用基数树压缩数据的提示:根据Wikipedia在上的文章,你可以构建并使用它来查找两个或多个字符串的公共子字符串(还提到它主要用于生物信息学)。为基数树的节点(或者至少是大于某个大小的节点)创建一个,您可以找到希望将它们拆分为较小节点的情况

    使用您的示例,“常规”(没有单独的子项)基数树将是:

    radix_tree = ("The quick ", {
        "b":("brown fox jumps over the lazy ", {
            "d":("dog.",{},1),
            "f":("frog.",{},3),
        }),
        "g":("green frog jumps over the lazy fox.", {}, 2),
    })
    
    这显然不能很好地压缩文本。但是在为每个节点中的一组单词创建后缀树之后,很明显,
    “跳过惰性”
    是一个很好的候选,可以在两个或多个节点中进行插入和重用(导致前面显示的示例)。节省的空间总是
    (string_length-(1..2)*sizeof_node)*num_nodes
    (1代表preffix/后缀,2代表rest),因此在进行此优化时根本不需要考虑短字符串


    是的,很复杂,正如Adam Mihalcin所指出的,纯Python解决方案很可能会因为成本太高而无法存储非常大的数据集。但如果没有现成的解决方案,我会首先尝试…

    中的链接可能会有所帮助。在这种规模下,您需要仔细考虑您的需求。例如,当你说“索引匹配”时,你的意思是它们是按你需要保留的特定顺序排列的,还是只需要按固定顺序排列?(前者比较难,因为相似的句子顺序可能不尽相同。)当你说“通配符匹配”时,你指的是前缀还是星号?(前者更容易,因为这样你就可以使用树型结构。)还要注意与真正的com的相似之处
    unique_strings = [ # Not a real array, just an hypothetical "intern table"
        "The quick ",
        "brown fox ",
        "green frog ",
        "jumps over the lazy ",
        "dog.",
        "fox.",
        "frog.",
    ]
    radix_trie = (0, {        # The quick *
        "b":(1, {             # The quick brown fox *
            "j":(3, {         # The quick brown fox jumps over the lazy *
                "d":(4,{},1), # The quick brown fox jumps over the lazy dog.
                "f":(6,{},3), # The quick brown fox jumps over the lazy frog.
            }),
        }),
        "g":(2, {             # The quick green frog *
            "j":(3, {         # The quick green frog jumps over the lazy *
                "f":(5,{},2), # The quick green frog jumps over the lazy fox.
            }),
        }),
    })
    # The nodes ("b", "j") and ("g", "j") wouldn't occur in a regular radix tree,
    # since they have no siblings. Adding them, however, gives a net gain of space.
    #
    # "jumps over the lazy " is a common substring of
    #     "brown fox jumps over the lazy " and
    #     "green frog jumps over the lazy fox."
    # which would occur naturally in a radix tree with only the 3 sentences given.
    paths = {
        1:("b", "j", "d"),
        2:("g", "j", "f"),
        3:("b", "j", "f"),
    }
    
    radix_tree = ("The quick ", {
        "b":("brown fox jumps over the lazy ", {
            "d":("dog.",{},1),
            "f":("frog.",{},3),
        }),
        "g":("green frog jumps over the lazy fox.", {}, 2),
    })