为什么只用 itemgetter 和 groupby 返回最后一个条目
why only the last entry is returned with itemgetter and groupby
我想知道下面的代码 returns 是否符合预期?
我 运行 在 Python 3.7.
我期待 "Expected" 输出,但只返回每个组的最后一个条目,如 "Actual" 所示。
import operator
import itertools
adict = {'a': 1, 'b':3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
dict((i, dict(v)) for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)))
Expected Output: {1: {'a': 1, 'c': 1, 'f':1}, 2: {'d': 2}, 3: {'b', 'e'} }
Actual : {1: {'f': 1}, 3: {'e': 3}, 2: {'d': 2}}
如果你分解 dict((i, dict(v)) for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)))
应该清楚为什么只有最后一个键值对在最后的字典中:
for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)):
print(i, dict(v))
产出
1 {'a': 1}
3 {'b': 3}
1 {'c': 1}
2 {'d': 2}
3 {'e': 3}
1 {'f': 1}
对其中的每一个调用 dict
将使用相同的外键覆盖先前创建的字典。
可以通过使用 defaultdict(dict)
来修复它,同时确保 update
现有的内部字典具有新的键值对:
from collections import defaultdict
adict = {'a': 1, 'b': 3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
output = defaultdict(dict)
for i, v in adict.items():
output[v][i] = v
print(output)
产出
defaultdict(<class 'dict'>, {1: {'a': 1, 'c': 1, 'f': 1}, 3: {'b': 3, 'e': 3}, 2: {'d': 2}})
您不必使用 defaultdict
,但它节省了存在性检查:
adict = {'a': 1, 'b': 3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
output = {}
for i, v in adict.items():
if v in output:
output[v][i] = v
else:
output[v] = {i: v}
print(output)
产出
{1: {'a': 1, 'c': 1, 'f': 1}, 3: {'b': 3, 'e': 3}, 2: {'d': 2}}
正如 Jon 在评论中提到的,这也可以通过先按相同的键 (operator.itemgetter(1)
) 对 adict.values
进行排序来解决:
dict((i, dict(v)) for i, v in itertools.groupby(sorted(adict.items(), key=itemgetter(1)), operator.itemgetter(1)))
此警告实际上在 itertools.groupby
documentation:
中提到
... Generally, the iterable needs to already be sorted on the same key function.
我想知道下面的代码 returns 是否符合预期?
我 运行 在 Python 3.7.
我期待 "Expected" 输出,但只返回每个组的最后一个条目,如 "Actual" 所示。
import operator
import itertools
adict = {'a': 1, 'b':3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
dict((i, dict(v)) for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)))
Expected Output: {1: {'a': 1, 'c': 1, 'f':1}, 2: {'d': 2}, 3: {'b', 'e'} }
Actual : {1: {'f': 1}, 3: {'e': 3}, 2: {'d': 2}}
如果你分解 dict((i, dict(v)) for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)))
应该清楚为什么只有最后一个键值对在最后的字典中:
for i, v in itertools.groupby(adict.items(), operator.itemgetter(1)):
print(i, dict(v))
产出
1 {'a': 1}
3 {'b': 3}
1 {'c': 1}
2 {'d': 2}
3 {'e': 3}
1 {'f': 1}
对其中的每一个调用 dict
将使用相同的外键覆盖先前创建的字典。
可以通过使用 defaultdict(dict)
来修复它,同时确保 update
现有的内部字典具有新的键值对:
from collections import defaultdict
adict = {'a': 1, 'b': 3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
output = defaultdict(dict)
for i, v in adict.items():
output[v][i] = v
print(output)
产出
defaultdict(<class 'dict'>, {1: {'a': 1, 'c': 1, 'f': 1}, 3: {'b': 3, 'e': 3}, 2: {'d': 2}})
您不必使用 defaultdict
,但它节省了存在性检查:
adict = {'a': 1, 'b': 3, 'c': 1, 'd': 2, 'e': 3, 'f': 1}
output = {}
for i, v in adict.items():
if v in output:
output[v][i] = v
else:
output[v] = {i: v}
print(output)
产出
{1: {'a': 1, 'c': 1, 'f': 1}, 3: {'b': 3, 'e': 3}, 2: {'d': 2}}
正如 Jon 在评论中提到的,这也可以通过先按相同的键 (operator.itemgetter(1)
) 对 adict.values
进行排序来解决:
dict((i, dict(v)) for i, v in itertools.groupby(sorted(adict.items(), key=itemgetter(1)), operator.itemgetter(1)))
此警告实际上在 itertools.groupby
documentation:
... Generally, the iterable needs to already be sorted on the same key function.