在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脚本有几个应用程序。
由于
答案 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))