2016-09-26 73 views
4

我有字典詞典,其撥低一個檔次或兩個看起來像這樣:字典操作

a = {114907: {114905: 1.4351310915, 
       114908: 0.84635577943, 
       114861: 61.490648372}, 
    113820: {113826: 8.6999361654, 
       113819: 1.1412795216, 
       111068: 1.1964946282, 
       117066: 1.5595617822, 
       113822: 1.1958951003}, 
    114908: {114906: 1.279878388, 
       114907: 0.77568252572, 
       114862: 2.5412545474} 
    } 

我想執行的操作如下:

有關的每一個關鍵:

  • 如果它的值(最裏面的字典,例如{114905: 1.435.., 114908: 0.846.., 114861: 61.490..})包含的鍵也出現在最外面的鍵上(在本例中爲114908),請用0123來自後者的值並完全刪除它。
  • 最後,將最外層的鍵轉換爲包含原始鍵和從最內層詞典中彈出的鍵的元組。

所需的輸出會是這樣:

b = {(114907, 114908): {114905: 1.4351310915, 
         114906: 1.279878388, 
         114862: 2.5412545474, 
         114861: 61.490648372}, 
    113820: {113826: 8.6999361654, 
       113819: 1.1412795216, 
       111068: 1.1964946282, 
       117066: 1.5595617822, 
       113822: 1.1958951003} 
    } 

我真的希望你得到了什麼,我想在這裏實現,因爲這甚至不是描。

這是我迄今爲止的,但它在幾個點失敗,我深信,我走錯了路。最終我會到達那裏,但這將是有史以來最無效的事情。

from copy import deepcopy 

temp = deepcopy(a) 
for item in temp: 
    for subitems, values in temp[item].items(): 
     if values < 1.0: 
      for k, v in temp[subitems].items(): 
       if k != item: 
        a[item][k] = v 
#     a[item].pop(subitems) 
for i in a: 
    print(i, a[i]) 
#114908 {114905: 1.4351310915, 114906: 1.279878388, 114907: 0.77568252572, 114861: 61.490648372, 114862: 2.5412545474} 
#114907 {114905: 1.4351310915, 114906: 1.279878388, 114908: 0.84635577943, 114861: 61.490648372, 114862: 2.5412545474} 
#113820 {113826: 8.6999361654, 113819: 1.1412795216, 111068: 1.1964946282, 117066: 1.5595617822, 113822: 1.1958951003} 

方的問題,爲什麼pop字典中返回value只,而不是key: value對?

編輯

一個重要的細節可能使事情更容易的是另一種方式來尋找什麼修改是內部字典值。如果他們低於1.0,他們的鍵也必然是外字典的鍵。

+0

如果兩個外鍵相互包含在它們各自的值中? –

+0

聽起來像是一個很好的方式把它@MosesKoledoye –

+0

如果114908的第一個內部鍵是114905而不是114906,你會期望什麼?組合的內部字典將會有重複的鍵。或者這是保證不可能的? –

回答

1

這應該工作

a = {114907: {114905: 1.4351310915, 
       114908: 0.84635577943, 
       114861: 61.490648372}, 
    113820: {113826: 8.6999361654, 
       113819: 1.1412795216, 
       111068: 1.1964946282, 
       117066: 1.5595617822, 
       113822: 1.1958951003}, 
    114908: {114906: 1.279878388, 
       114907: 0.77568252572, 
       114862: 2.5412545474} 
    } 

# Lets call the keys leaders and its value is a dict of 
# keys (call them members) to floats. 
# if a member is also a leader, then the two leaders combine. 

leaders = set(a.keys()) 
leaders_to_members = { leader: set(member_dict.keys()) for leader, member_dict in a.items() } 
seen_leaders =set() 
b = {} 
for leader, members in leaders_to_members.items(): 
    if leader in seen_leaders: 
     continue 

    members_as_leaders = members.intersection(leaders) 
    members_as_leaders.add(leader) 

    v = {} 
    for member_leader in members_as_leaders: 
     v.update(a[member_leader]) 

    seen_leaders.update(members_as_leaders) 

    # if its just one element, you want it as the key directly 
    b_key = tuple(members_as_leaders) if len(members_as_leaders) > 1 else members_as_leaders.pop() 
    # as per your output, you've removed the key to float value if it is a leader 
    b_val = { k: float_val for k, float_val in v.items() if k not in members_as_leaders } 
    b[b_key] = b_val 

print(b) 

輸出

{113820: {111068: 1.1964946282, 
      113819: 1.1412795216, 
      113822: 1.1958951003, 
      113826: 8.6999361654, 
      117066: 1.5595617822}, 
(114907, 114908): {114861: 61.490648372, 
        114862: 2.5412545474, 
        114905: 1.4351310915, 
        114906: 1.279878388}} 

側問題:值對:爲什麼流行的字典,而不是關鍵返回值?

>>> a.pop() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: pop expected at least 1 arguments, got 0 

>>> help(a.pop) 
""" 
Help on built-in function pop: 

pop(...) method of builtins.dict instance 
    D.pop(k[,d]) -> v, remove specified key and return the corresponding value. 
    If key is not found, d is returned if given, otherwise KeyError is raised 
""" 

正如你所看到的,彈出預計的關鍵,因此它可以在彈出的價值。既然你需要給它鑰匙,它不必把鑰匙還給你。

0
# for each "primary key" 
for primary in a.keys(): 
    # for each "sub-key" 
    for sub_key in a[primary].keys(): 
     # if the sub-key is also a primary key 
     if sub_key in a.keys(): 
      # assign to the subkey the value of its corresponding primary key 
      a[primary][sub_key] = a[sub_key] 

這是你在找什麼,至少在你的問題的第一部分?

+0

不完全。只需運行它並將您的輸出與所需的輸出進行比較即可。這與我正在做的類似,除了你不扁平內部字典。 –

0

如何:

import itertools 

b ={} 

for k1,v1 in a.items(): 
    for k2,v2 in v1.items(): 
     if k2 in a: 
      a[k2].pop(k1) 
      a[k1].pop(k2) 
      dest = dict(itertools.chain(a[k1].items(), a[k2].items())) #python 2.7 

      b[(k1,k2)] = dest 

print b 

答案:

{(114908, 114907): {114905: 1.4351310915, 114906: 1.279878388, 114861: 61.490648372, 114862: 2.5412545474}} 
1

在Python3.x,{}.keys()返回一個視圖。你可以在字典視圖上使用set操作。

所以你的算法在一定程度上簡化爲:

outer=a.keys() 
deletions=set() 
new_a={} 
for k,di in a.items(): 
    c=outer & di.keys() 
    if c: 
     c=c.pop() 
     if (c,k) not in deletions: 
      deletions.add((k,c)) 
    else: 
     new_a[k]=di 

for t in deletions: 
    del a[t[0]][t[1]], a[t[1]][t[0]] 
    new_a[t]=a[t[0]] 
    new_a[t].update(a[t[1]]) 
>>> new_a 
{113820: {113826: 8.6999361654, 
      113819: 1.1412795216, 
      111068: 1.1964946282, 
      117066: 1.5595617822, 
      113822: 1.1958951003}, 
(114908, 114907): {114905: 1.4351310915, 
        114906: 1.279878388, 
        114861: 61.490648372, 
        114862: 2.5412545474}} 

元組可以根據迭代的順序和設置操作的順序改變元素的順序。兩者都是無序的字典。由於元素可能會有所不同,哪些字典用作更新字典也是無序的。

該功能也只適用於單個路口;即沒有多於2個元素創建的元組作爲關鍵字。