【问题标题】:Ruby: hash that doesn't remember key valuesRuby:不记得键值的哈希
【发布时间】:2011-05-26 17:29:04
【问题描述】:

是否有不记得键值的散列实现?我必须做一个巨大的哈希,但我不在乎键是什么。

编辑:

Ruby 的哈希实现存储键的值。我想要不记得键值的哈希。它只是使用哈希函数来存储您的值而忘记了密钥。这样做的原因是我需要为大约 5 gb 的数据做一个哈希,我不在乎创建它之后的键值是什么。我只想能够根据其他键查找值。

编辑编辑:

语言有点混乱。通过键的值,我的意思是:

hsh['value'] = 数据

我不在乎散列函数在散列中存储数据后的“值”是什么。

编辑^3:

好的,这就是我正在做的事情:我正在为一组多个基因生成每个 35 个字母(核苷酸)的 kmer。每个基因都有一个 ID。哈希看起来像这样:

kmers = { 'A...G' => [1, 5, 3], 'G...T' => [4, 9, 9, 3]  }

所以哈希键是kmer,值是一个数组,其中包含具有该kmer的基因/字符串的ID。

我正在另一个数据集中查询 kmers 的哈希值,以快速找到匹配的基因。我不在乎哈希键是什么,我只需要从 kmer 中获取数字数组。

>> kmers['A...G']
=> [1, 5, 3]

>> kmers.keys.first
=> "Sorry Dave, I can't do that"

【问题讨论】:

  • 为什么不用使用数组来代替?
  • 你在找一套吗?也许是一个数组?
  • 您是否只想检查某个元素是否在其中/全部迭代,还是仍需要通过其唯一(未知)键访问特定元素?
  • 您是否正在寻找一个允许您通过密钥查找但不会存储密钥的容器?我不认为,这将与哈希一起工作,因为即使它根据键的哈希值存储值,由于通常不可避免的哈希值冲突,仅哈希值不足以进行查找。
  • 这仍然令人困惑。你能否提供一个真实的例子来说明你需要存储什么以及你需要对该集合进行哪些操作?

标签: ruby bioinformatics


【解决方案1】:

我猜你想要一个 set,尽管它存储了唯一的键并且没有值。它具有从哈希中快速查找的时间。 Set 包含在标准库中。

require 'set'
s = Set.new
s << 'aaa'
p s.merge(['ccc', 'ddd'])  #=> #<Set: {"aaa", "ccc", "ddd"}>

【讨论】:

    【解决方案2】:

    即使有一个奇怪的哈希只是记录了存在(这就是我理解问题的方式)你可能不想使用它,因为内置的哈希会更简单,更快,不需要 gem,等等。所以只需设置...

     h[k] = k
    

    ...收工了...

    【讨论】:

    • 我必须对 5 gig 字符串的每个唯一的 35 个字母 kmer 进行哈希处理。我希望已经为我制作了一个不错的 C 实现 :) 但我想我现在只需要尝试编写一个。
    • 5 GB?哇。在任何情况下,请查看 Ruby Inline 寻找一个可以让您更轻松地编写自定义 C 代码的简洁 gem。使用 Ruby 内联的一个很好的例子是 ImageScience。
    • 知道了,你需要一个带有散列函数的散列映射实现,而不是这个简单的存储键。这真的很好。我会尝试多挖一点,看看是否有类似的东西用于 ruby​​。
    • @NeX,我不知道 Ruby(除了它的名字)。您是说默认情况下 Ruby 哈希不使用哈希函数吗? IE。哈希只不过是一对数组?除非它使用其他技巧,否则性能会很慢。
    • 性能并不是这里真正的问题。如果不存储密钥而仅用于生成某种唯一引用,则内存使用率可能会大大提高。同样,为了实现这一点,必须存在一些约束。使用任何对象作为键确实很棒,但并不真正适用于这种场景。
    【解决方案3】:

    我假设 5 gb 字符串是一个基因组,而 kmer 是 35 个碱基对核苷酸序列。

    我可能会做的(稍微简化)是:

    human_genome = File.read("human_genome.txt")
    human_kmers = Set.new
    human_genome.each_cons(35) do |potential_kmer|
      human_kmers << potential_kmer unless human_kmers.include?(potential_kmer)
    end
    unknown_gene = File.read("unknown_gene.txt")
    related_to_humans = unknown_gene.each_cons(35).any? do |unknown_gene_kmer|
      human_kmers.include?(unknown_gene_kmer)
    end
    

    【讨论】:

    • 这是一个很好的现实生活例子(遗憾的是,我们仍在等待奥斯汀提供更多信息)。这里唯一的问题是,看起来这个人的键与存储的值不匹配,所以我们仍然需要一个键 => 值集合:S
    • 关闭,这是一个基因数据库。我需要知道哪个特定基因有一个kmer。所以我不能只检查一个集合是否包含它。我可以为每个基因创建集合,但这需要很长时间。
    【解决方案4】:

    我必须做一个巨大的哈希,但我不在乎键是什么。

    这就是所谓的数组。只需使用一个数组。没有键的散列根本不是散列并且失去了它的价值。如果您不需要键值查找,则不需要哈希。

    【讨论】:

    • 不,这称为哈希。 Ruby 的哈希实现存储密钥。我需要一个不存储键的散列,而只是散列查询并返回值。
    • @Austin:您不能只是“对查询进行哈希处理并返回值”-您仍然需要检查键是否实际上相等(并且相等的哈希值不会告诉您)和您需要存储密钥。
    • 是的,这个问题没有任何意义。我不知道如何帮助你。如果您需要通过键查找值,您显然需要存储该键。
    • 这不是真的。基于哈希的当前 ruby​​ 实现,需要存储键(因为它接受任何对象作为键,所以对象引用将一直存在,直到哈希被销毁)但奥斯汀似乎正在寻找另一种键 => 值集合。撇开 Hash 在 ruby​​ 上的工作原理不谈,我们可以讨论哈希键、哈希函数和哈希表。给定一个散列函数,我们应该能够提交一个键(有一些约束),使用散列函数动态处理它,并根据散列函数结果访问集合的记录。
    • @NeX:当然,您可以将它放入基于哈希的数组索引中,然后丢弃它。您必须记住,我的回复是基于在进行任何修改之前的原始帖子。
    【解决方案5】:

    使用数组。 Array 按整数而不是键索引。 http://www.ruby-doc.org/core/classes/Array.html

    a = []
    a << "hello"
    puts a #=> ["hello"]
    

    【讨论】:

      猜你喜欢
      • 2011-06-30
      • 2021-12-07
      • 1970-01-01
      • 2011-07-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      相关资源
      最近更新 更多