用值切片字典
slicing dictionary with values
我有这样的字典:
d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
我想对这个字典进行切片,如果最后的值相同,它应该 return 只有遇到的第一个值。所以 return 是:
d = {1: 'a', 2:'b', 3:'c'}
我正在使用 collections.defaultdict(OrderedDict)
来维护按键排序。
目前,我正在使用循环。有没有一种 pythonic 的方式来做到这一点?
更新
字典值也可以是字典:
d = {1: {'a': 'a1', 'b': 'b1'}, 2:{'a': 'a1', 'b': 'b2'}, 3:{'a': 'a1', 'b': 'c1'}, 4:{'a': 'a1', 'b': 'c1'}, 5:{'a': 'a1', 'b': 'c1'}, 6:{'a': 'a1', 'b': 'c1'}}
输出:
d = {1: {'a': 'a1', 'b': 'b1'}, 2:{'a': 'a1', 'b': 'b2'}, 3:{'a': 'a1', 'b': 'c1'}}
如果你想摆脱 for 循环 - 你可以这样做:
{a:b for b,a in {y:x for x,y in sorted(d.iteritems(), reverse=True)}.iteritems()}
但它不是那么pythonic,也不是那么高效。
不是使用带有代表索引的键的有序字典,更pythonic的方法是使用列表。在这种情况下,您将使用索引而不是键,并且能够更有效地对列表进行切片。
>>> d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
>>> a = list(d.values())
>>> a[:a.index(a[-1])+1]
['a', 'b', 'c']
以防万一,pandas
的解决方案
import pandas as pd
df = pd.DataFrame(dict(key=list(d.keys()),val=list(d.values())))
print(df)
key val
0 1 a
1 2 b
2 3 c
3 4 c
4 5 c
5 6 c
df = df.drop_duplicates(subset=['val'])
df.index=df.key
df.val.to_dict()
{1: 'a', 2: 'b', 3: 'c'}
不知道最大数据集上的性能问题或者它是否更像 pythonic。
尽管如此,没有循环。
您可以检查最后两个值是否相同:
d = OrderedDict({1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'})
while d.values()[-1] == d.values()[-2]:
d.popitem()
print d
# OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])
您可以使用 itertools.groupy
和 list-comprehension 来实现您的结果
>>> from itertools import groupby
>>> d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
>>> n = [(min([k[0] for k in list(g)]),k) for k,g in groupby(d.items(),key=lambda x: x[1])]
>>> n
>>> [(1, 'a'), (2, 'b'), (3, 'c')]
上面的表达式也可以写成
>>> from operator import itemgetter
>>> n = [(min(map(itemgetter(0), g)), k) for k, g in groupby(d.items(), key=itemgetter(1))]
您只需使用
即可将其转换为 dict
>>> dict(n)
>>> {1: 'a', 2: 'b', 3: 'c'}
这显然不维护键的顺序,所以你可以使用OrderedDict
>>> OrderedDict(sorted(n))
>>> OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])
我有这样的字典:
d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
我想对这个字典进行切片,如果最后的值相同,它应该 return 只有遇到的第一个值。所以 return 是:
d = {1: 'a', 2:'b', 3:'c'}
我正在使用 collections.defaultdict(OrderedDict)
来维护按键排序。
目前,我正在使用循环。有没有一种 pythonic 的方式来做到这一点?
更新
字典值也可以是字典:
d = {1: {'a': 'a1', 'b': 'b1'}, 2:{'a': 'a1', 'b': 'b2'}, 3:{'a': 'a1', 'b': 'c1'}, 4:{'a': 'a1', 'b': 'c1'}, 5:{'a': 'a1', 'b': 'c1'}, 6:{'a': 'a1', 'b': 'c1'}}
输出:
d = {1: {'a': 'a1', 'b': 'b1'}, 2:{'a': 'a1', 'b': 'b2'}, 3:{'a': 'a1', 'b': 'c1'}}
如果你想摆脱 for 循环 - 你可以这样做:
{a:b for b,a in {y:x for x,y in sorted(d.iteritems(), reverse=True)}.iteritems()}
但它不是那么pythonic,也不是那么高效。
不是使用带有代表索引的键的有序字典,更pythonic的方法是使用列表。在这种情况下,您将使用索引而不是键,并且能够更有效地对列表进行切片。
>>> d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
>>> a = list(d.values())
>>> a[:a.index(a[-1])+1]
['a', 'b', 'c']
以防万一,pandas
import pandas as pd
df = pd.DataFrame(dict(key=list(d.keys()),val=list(d.values())))
print(df)
key val
0 1 a
1 2 b
2 3 c
3 4 c
4 5 c
5 6 c
df = df.drop_duplicates(subset=['val'])
df.index=df.key
df.val.to_dict()
{1: 'a', 2: 'b', 3: 'c'}
不知道最大数据集上的性能问题或者它是否更像 pythonic。
尽管如此,没有循环。
您可以检查最后两个值是否相同:
d = OrderedDict({1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'})
while d.values()[-1] == d.values()[-2]:
d.popitem()
print d
# OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])
您可以使用 itertools.groupy
和 list-comprehension 来实现您的结果
>>> from itertools import groupby
>>> d = {1: 'a', 2:'b', 3:'c', 4:'c', 5:'c', 6:'c'}
>>> n = [(min([k[0] for k in list(g)]),k) for k,g in groupby(d.items(),key=lambda x: x[1])]
>>> n
>>> [(1, 'a'), (2, 'b'), (3, 'c')]
上面的表达式也可以写成
>>> from operator import itemgetter
>>> n = [(min(map(itemgetter(0), g)), k) for k, g in groupby(d.items(), key=itemgetter(1))]
您只需使用
即可将其转换为dict
>>> dict(n)
>>> {1: 'a', 2: 'b', 3: 'c'}
这显然不维护键的顺序,所以你可以使用OrderedDict
>>> OrderedDict(sorted(n))
>>> OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])