将值合并到Ordered Dict中的一个键

时间:2018-03-15 21:27:31

标签: python python-3.x ordereddictionary

所以我想知道是否有一个更优雅的解决方案,我现在已经实现了合并有序字典的值。

我有一个看起来像这样的有序词典

'fields': OrderedDict([
    ("Sample Code", "Vendor Sample ID"),
    ("Donor ID", "Vendor Subject ID"),
    ("Format", "Material Format"),
    ("Sample Type", "Sample Type"),
    ("Age", "Age"),
    ("Gender", "Gender"),
    ("Ethnicity/ Race", "Race"),
]),

如果我传入一个像列表那样的参数

[2,3] or [2,4,5]

是否有一种优雅的方法可以在新密钥下将值合并在一起

[2,3], "Random_Key"

将返回

'fields': OrderedDict([
        ("Sample Code", "Vendor Sample ID"),
        ("Donor ID", "Vendor Subject ID"),
        **("Random Key", "Material Format Sample Type"),**
        ("Age", "Age"),
        ("Gender", "Gender"),
        ("Ethnicity/ Race", "Race"),
    ]),

同时还删除字典中的键?

3 个答案:

答案 0 :(得分:1)

不确定那是一种优雅的方式。 OrderedDict使用move_to_end方法在开始或结束时移动键,但不是在随机位置。

我尝试尽可能高效,并尽量减少循环

  • 获取密钥列表
  • 找到要与以下内容合并的键的索引
  • 删除词典的下一个键
  • 使用d个项目
  • 创建一个列表
  • 使用存储索引
  • 中的新值更改此列表
  • 从中重建OrderedDict
像这样(我删除了一些键,因为它缩短了示例):

from collections import OrderedDict

d = OrderedDict([
    ("Sample Code", "Vendor Sample ID"),
    ("Donor ID", "Vendor Subject ID"),
    ("Format", "Material Format"),
    ("Sample Type", "Sample Type"),
    ("Age", "Age"),
    ("Gender", "Gender"),
])

lk = list(d.keys())
index = lk.index("Sample Type")
v = d.pop(lk[index+1])

t = list(d.items())
t[index] = ("new key",t[index][1]+" "+v)

d = OrderedDict(t)

print(d)

结果:

  

OrderedDict([('示例代码','供应商样本ID'),'捐赠者ID','供应商主题ID' ),('格式','材料格式'),('新密钥','样本类型年龄'),(' ;性别','性别')])

答案 1 :(得分:1)

这也可以通过发电机很好地完成。

如果不需要压扁关键项目对,则此生成器生成关键项目对,如果有,则将项目保存到最后一个条目,然后生成它,使用新密钥并保存已加入的项目。

使用生成器可以构造新的OrderedDict。

from collections import OrderedDict    

def sqaushDict(d, ind, new_key):
    """ Takes an OrderedDictionary d, and yields its key item pairs, 
    except the ones at an index in indices (ind), these items are merged 
    and yielded at the last position of indices (ind) with a new key (new_key)
    """
    if not all(x < len(d) for x in ind):
        raise IndexError ("Index out of bounds")
    vals = []
    for n, (k, i), in enumerate(d.items()):
        if n in ind:
            vals += [i]
            if n == ind[-1]:
                yield (new_key, " ".join(vals))
        else:
            yield (i, k)

d = OrderedDict([
    ("Sample Code", "Vendor Sample ID"),
    ("Donor ID", "Vendor Subject ID"),
    ("Format", "Material Format"),
    ("Sample Type", "Sample Type"),
    ("Age", "Age"),
    ("Gender", "Gender"),
])

t = OrderedDict(squashDict(d, [2, 3], "Random"))
print(t)

答案 2 :(得分:0)

您可以通过对索引降序进行排序来优化此项,然后您可以使用dict.pop(key,None)一次检索并删除键/值,但我决定反对它,按{{{{{{{{{ 1}}。

indices

输出:

from collections import OrderedDict
from pprint import pprint

def mergeEm(d,indices,key):
    """Merges the values at index given by 'indices' on OrderedDict d into a list.        
    Appends this list with key as key to the dict. Deletes keys used to build list."""

    if not all(x < len(d) for x in indices):
        raise IndexError ("Index out of bounds")

    vals = []                      # stores the values to be removed in order
    allkeys = list(d.keys())
    for i in indices:
        vals.append(d[allkeys[i]])   # append to temporary list
    d[key] = vals                  # add to dict, use ''.join(vals) to combine str
    for i in indices:              # remove all indices keys
        d.pop(allkeys[i],None)
    pprint(d)


fields= OrderedDict([
    ("Sample Code", "Vendor Sample ID"),
    ("Donor ID", "Vendor Subject ID"),
    ("Format", "Material Format"),
    ("Sample Type", "Sample Type"),
    ("Age", "Age"),
    ("Gender", "Gender"),
    ("Ethnicity/ Race", "Race"),
    ("Sample Type", "Sample Type"),
    ("Organ", "Organ"),
    ("Pathological Diagnosis", "Diagnosis"),
    ("Detailed Pathological Diagnosis", "Detailed Diagnosis"),
    ("Clinical Diagnosis/Cause of Death", "Detailed Diagnosis option 2"),
    ("Dissection", "Dissection"),
    ("Quantity (g, ml, or ug)", "Quantity"),
    ("HIV", "HIV"),
    ("HEP B", "HEP B")
])
pprint(fields)
mergeEm(fields, [5,4,2], "tata")