您如何根据字典的值对字典进行排序,然后将这些值相加到一定程度?

时间:2018-11-16 15:26:58

标签: julia

我想知道最好的方法是根据该值对Dict {String,Int}类型的字典进行排序。我遍历包含多个序列记录的FASTQ文件,每个记录都有一个字符串作为标识符(用作键)和另一个字符串,其中我取长度作为键的值。

例如:

    testdict["ee0a"]=length("aatcg")
    testdict["002e4"]=length("aatcgtga")
    testdict["12-f9"]=length(aatcgtgacgtga")

在这种情况下,键值对将为"ee0a" => 5"002e4" => 8"12-f9" => 13

我想要做的是将这些对从最高值到最低值进行排序,然后我将这些值以不同的方式求和,直到变量通过某个阈值为止。然后,我需要保存我使用过的密钥,以便以后可以使用它们。

是否可以使用sort()函数或使用SortedDict实现此目的?我可以想象,如果排序成功,我可以使用while循环将我的键添加到列表中,然后将我的值添加到另一个变量中,直到它大于我的阈值,然后使用键列表与我一起创建新字典选定的键值对。

但是最快的方法是什么?我读取的FASTQ文件可以包含多个GB的数据,所以我很想在读取文件时创建一个排序的字典,并选择我想要的记录,然后再对数据进行其他操作。

2 个答案:

答案 0 :(得分:0)

如果您的文件包含多个GB的数据,那么我会避免将它们首先存储在Dict中。我认为最好顺序处理文件并将满足条件的密钥存储在PriorityQueue包中的DataStructures.jl中。当然,如果您从内存中的字典中读取数据,则可以重复相同的过程(只需将源文件从磁盘文件更改为字典)

这是您可以考虑的伪代码(完整的解决方案将取决于您如何读取未指定的数据)。 假设您要存储元素,直到它们执行的阈值保持THRESH不变为止。

pq = PriorityQueue{String, Int}()
s = 0

while (there are more key-value pairs in source file)
    key, value = read(source file)
    # this check avoids adding a key-value pair for which we are sure that
    # it is not interesting
    if s <= THRESH || value > peek(pq)[2]
        enqueue!(pq, key, value)
        s += value
        # if we added something to the queue we have to check
        # if we should not drop smallest elements from it
        while s - peek(pq)[2] > THRESH
            s -= dequeue!(pq)[2]
        end
    end
end

在此过程之后,pq将仅保留您感兴趣的键值对。此方法的主要好处是您无需将整个数据存储在RAM中。在任何时间点,您都只存储在数据处理此阶段将选择的键值对。

请注意,此过程不会为您提供容易预测的结果,因为多个键可能具有相同的值。而且,如果此值在截止边界上,您将不知道将保留哪个值(但是,在这种特殊情况下,您未指定要执行的操作-如果您指定此情况下的要求,则应更新算法一点)。

答案 1 :(得分:0)

如果您有足够的内存来容纳至少一个或两个所需大小的完整Dict,则可以使用长度为键的倒置Dict,并使用旧键数组作为值,以避免重复数据丢失相同键的长度值。

我认为下面的代码就是您的问题所导致的方向:

d1 = Dict("a" => 1, "b" => 2, "c" => 3, "d" => 2, "e" => 1, "f" =>5)

d2 = Dict()
for (k, v) in d1
    d2[v] = haskey(d2, v) ? push!(d2[v], k) : [k]
end

println(d1)
println(d2)

for k in sort(collect(keys(d2)))
    print("$k, $(d2[k]);  ")
    # here can delete keys under a threshold to speed further processing
end

如果您没有足够的内存来容纳整个Dict,则可能会受益 首先将数据放入像SQLite这样的SQL数据库中,然后执行 查询而不是修改内存中的Dict。在这种情况下,一栏 表中的将是数据,您将为数据长度添加一列 到SQLite表。或者,您可以像上面的答案一样使用PriorityQueue。