将字典转换为按值排序的列表,每个项目具有多个值

时间:2013-10-30 06:14:25

标签: python dictionary

在Python中,我有一个转换列表和字典的简单问题,我使用显式类型检查解决了这些问题,以区分整数和整数列表。我对python有些新意,我很好奇是否有更'pythonic'方法来解决问题,即。这避免了明确的类型检查。

简而言之:尝试使用值对字典的键进行排序,但每个键可以有多个值,并且键需要在列表中多次出现。数据的格式为{'a':1, 'b':[0,2],...}。我所提出的所有内容(使用sorted(,key =))都会因为一次出现的值而不是整数而不是列表1的长度而被绊倒。

我想在{'a':3, 'b':0, 'c':[2,4], 'd':[1,5]}形式的字典和列表['b', 'd', 'c', 'a', 'c', 'd']之间进行转换(列表中项目的位置由字典中的值指定)。

函数list_to_dictionary应该为列表中出现的每个项目都有一个键,其值为列表中的位置。如果项目出现多次,则该值应为存储所有这些位置的列表。

函数dictionary_to_list应创建一个由字典键组成的列表,按值排序。如果值不是单个整数而是整数列表,则该键应在相应的排序位置多次出现在列表中。

我的解决方案如下:

def dictionary_to_list(d):
"""inputs a dictionary a:i or a:[i,j], outputs a list of a sorted by i"""    
    #Converts i to [i] as value of dictionary
    for a in d:
        if type(d[a])!=type([0,1]):
            d[a] = [d[a]]

    #Reverses the dictionary from {a:[i,j]...} to {i:a, j:a,...}
    reversed_d ={i:a for a in d for i in d[a]}

    return  [x[1] for x in sorted(reversed_d.items(), key=lambda x:x[0])]

def list_to_dictionary(x):
    d = {}        
    for i in range(len(x)):
        a = x[i]            
        if a in d:
            d[a].append(i)
        else:
            d[a]=[i]
    #Creates {a:[i], b:[j,k],...}

    for a in d:
        if len(d[a])==1:
            d[a] = d[a][0]
    #Converts to {a:i, b:[j,k],...}

    return d

由于与我的其余代码的交互,我无法将问题更改为将长度为1的列表代替单个整数作为字典的值。似乎应该有一个简单的方法来处理这个,但我无法弄明白。这里更好的解决方案是我的python脚本有几个应用程序。

由于

3 个答案:

答案 0 :(得分:1)

def dictionary_to_list(data):
    result = {}
    for key, value in data.items():
        if isinstance(value, list):
            for index in value:
                result[index] = key
        else:
            result[value] = key
    return [result[key] for key in sorted(result)]

def list_to_dictionary(data):
    result = {}
    for index, char in enumerate(data):
        result.setdefault(char, [])
        result[char].append(index)
    return dict((key, value[0]) if len(value) == 1 else (key, value) for key, value in result.items())

dictData = {'a':3, 'b':0, 'c':[2,4], 'd':[1,5]}
listData = ['b', 'd', 'c', 'a', 'c', 'd']

print dictionary_to_list(dictData)
print list_to_dictionary(listData)

<强>输出

['b', 'd', 'c', 'a', 'c', 'd']
{'a': 3, 'c': [2, 4], 'b': 0, 'd': [1, 5]}

答案 1 :(得分:1)

In [17]: d = {'a':3, 'b':0, 'c':[2,4], 'd':[1,5]}

In [18]: sorted(list(itertools.chain.from_iterable([[k]*(1 if isinstance(d[k], int) else len(d[k])) for k in d])), key=lambda i:d[i] if isinstance(d[i], int) else d[i].pop(0))
Out[18]: ['b', 'd', 'c', 'a', 'c', 'd']

电话会议是:

sorted(
  list(
    itertools.chain.from_iterable(
      [[k]*(1 if isinstance(d[k], int) else len(d[k])) 
        for k in d
      ]
    )
  ), 
  key=lambda i:d[i] if isinstance(d[i], int) else d[i].pop(0)
)

我们的想法是第一部分(即list(itertools.chain.from_iterable([[k]*(1 if isinstance(d[k], int) else len(d[k])) for k in d]))创建d中的键列表,重复与之关联的值的数量。因此,如果一个键具有单{{1} (或只包含一个int)的列表作为其值,它在此列表中出现一次;否则,它出现的次数与列表中的项目一样多。

接下来,我们假设对值进行了排序(除了作为预处理步骤之外,这是微不足道的,否则)。所以现在,我们要做的是按照第一个值对键进行排序。如果它们只有一个int作为它们的值,则考虑它;否则,列表中包含其所有值的第一个元素。第一个元素也从列表中删除(通过调用pop),以便后续出现的相同键不会重用相同的值

如果您希望在没有明确的类型检查的情况下执行此操作,那么您可以将所有值分类为预处理步骤:

int

答案 2 :(得分:0)

def dictionary_to_list(d):
    return [k[0] for k in sorted(list(((key,n) for key, value in d.items() if isinstance(value, list) for n in value))+\
    [(key, value) for key, value in d.items() if not isinstance(value, list)], key=lambda k:k[1])]

def list_to_dictionary(l):
    d = {}
    for i, c in enumerate(l):
        if c in d:
            if isinstance(d[c], list):
                d[c].append(i)
            else:
                d[c] = [d[c], i]
        else:
            d[c] = i
    return d
l = dictionary_to_list({'a':3, 'b':0, 'c':[2,4], 'd':[1,5]})
print(l)
print(list_to_dictionary(l))