dictionary - Julia - 迭代字典中的键组合

标签 dictionary iterator julia

是否有一种巧妙的方法来迭代字典中的键组合?

我的字典具有如下值:

[1] => [1,2], [2,3] => [15], [3] => [6,7,8], [4,9,11] => [3], ... 

我需要做的是获取长度为1:n的所有键组合,其中n可能是fx 3

就像上面的例子一样,我想迭代

[[1], [3], [2,3], [[1],[1,2]], [[3],[2,3]], [4,9,11]]

我知道我可以只收集 key ,但我的字典相当大,而且我正在重新设计整个算法,因为当 n > 3 时它开始疯狂交换,极大地降低了效率

tl;dr有没有一种方法可以从字典创建组合迭代器而无需收集字典?

最佳答案

以下是一个直接的实现,它试图尽量减少对字典的查询。此外,它使用 OrderedDict,因此保留键索引是有意义的(因为 Dict 不保证每次都保持一致的键迭代,从而保证有意义的键索引)。

using Iterators
using DataStructures

od = OrderedDict([1] => [1,2], [2,3] => [15], [3] => [6,7,8], [4,9,11] => [3])

sv = map(length,keys(od))        # store length of keys for quicker calculations
maxmaxlen = sum(sv)              # maximum total elements in good key
for maxlen=1:maxmaxlen           # replace maxmaxlen with lower value if too slow
  @show maxlen
  gsets = Vector{Vector{Int}}()  # hold good sets of key _indices_
  for curlen=1:maxlen
    foreach(x->push!(gsets,x),
     (x for x in subsets(collect(1:n),curlen) if sum(sv[x])==maxlen))
  end
  # indmatrix is necessary to run through keys once in next loop
  indmatrix = zeros(Bool,length(od),length(gsets))
  for i=1:length(gsets)              for e in gsets[i]
      indmatrix[e,i] = true
    end
  end
  # gkeys is the vector of vecotrs of keys i.e. what we wanted to calculate
  gkeys = [Vector{Vector{Int}}() for i=1:length(gsets)]
  for (i,k) in enumerate(keys(od))
    for j=1:length(gsets)
      if indmatrix[i,j]
        push!(gkeys[j],k)
      end
    end
  end
  # do something with each set of good keys
  foreach(x->println(x),gkeys)
end

这比您目前的效率更高吗?最好将代码放入函数中或将其转换为 Julia 任务,该任务在每次迭代时生成下一个键集。

--- 更新 ---

使用 https://stackoverflow.com/a/41074729/3580870 中任务中关于迭代器的答案

改进的迭代器化版本是:

function keysubsets(n,d)
  Task() do
    od = OrderedDict(d)
    sv = map(length,keys(od))        # store length of keys for quicker calculations
    maxmaxlen = sum(sv)              # maximum total elements in good key
    for maxlen=1:min(n,maxmaxlen)    # replace maxmaxlen with lower value if too slow
      gsets = Vector{Vector{Int}}()  # hold good sets of key _indices_
      for curlen=1:maxlen
        foreach(x->push!(gsets,x),(x for x in subsets(collect(1:n),curlen) if sum(sv[x])==maxlen))
      end
      # indmatrix is necessary to run through keys once in next loop
      indmatrix = zeros(Bool,length(od),length(gsets))
      for i=1:length(gsets)              for e in gsets[i]
          indmatrix[e,i] = true
        end
      end
      # gkeys is the vector of vecotrs of keys i.e. what we wanted to calculate
      gkeys = [Vector{Vector{Int}}() for i=1:length(gsets)]
      for (i,k) in enumerate(keys(od))
        for j=1:length(gsets)
          if indmatrix[i,j]
            push!(gkeys[j],k)
          end
        end
      end
      # do something with each set of good keys
      foreach(x->produce(x),gkeys)
    end
  end
end

现在可以通过这种方式迭代所有键子集,直到组合大小为 4(在运行其他 StackOverflow 答案中的代码之后):

julia> nt2 = NewTask(keysubsets(4,od))
julia> collect(nt2)
10-element Array{Array{Array{Int64,1},1},1}:
 Array{Int64,1}[[1]]          
 Array{Int64,1}[[3]]          
 Array{Int64,1}[[2,3]]        
 Array{Int64,1}[[1],[3]]      
 Array{Int64,1}[[4,9,11]]     
 Array{Int64,1}[[1],[2,3]]    
 Array{Int64,1}[[2,3],[3]]    
 Array{Int64,1}[[1],[4,9,11]] 
 Array{Int64,1}[[3],[4,9,11]] 
 Array{Int64,1}[[1],[2,3],[3]]

(链接的 StackOverflow 答案中 NewTask 的定义是必要的)。

关于dictionary - Julia - 迭代字典中的键组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41058435/

相关文章:

python - 我删除了我的字典,但我的 dict_keys 不介意,这是为什么?

python - 如何以 json 格式(双引号) pretty-print (人类可读打印)Python dict?

iterator - 为什么 .flat_map() 和 .chars() 不适用于 std::io::Lines,但适用于字符串向量?

dictionary - 通过对相同键的值求和在 Julia 中添加字典

excel - 在 Julia 中从数据框转到 excel 文件时出错

time - 有没有办法让 'now'(至少)在 Julia 中达到毫秒精度?

r - 如何使用 plot_geo() 创建等值线图?

python - 更改Python字典中键的值

c++ - 错误 C2440 : '<function-style-cast>' : cannot convert from 'LinkedList<int>::Node *' to 'LinkedListIterator<const T>'

java - java迭代器似乎正在丢失数据