【问题标题】:counting string switches in a list with groupby使用 groupby 计算列表中的字符串开关
【发布时间】:2019-03-19 15:47:52
【问题描述】:

我头疼,字典是这样的:

{a: ['+','+','-','-','+','-','-','+'],
b: ['+','+','+','-','-','+','+','+','-'],
c: ['-','-','-','+','+','+']}

我想知道值的字符串改变了多少次,像这样:

a = 4
b = 3
c = 1

我尝试过使用 itertools 中的 groupby,方法是这样做:

for k, v in mydict.iteritems():
    print k + ' ' + str([len(list(g[1])) for g in groupby(list(v)) if g[0] =='+'])

但我只得到一个包含两个值的列表(两个字符串开关).. 我已尝试更改 '+' 和 '-' 字符但没有成功,有什么建议吗?

【问题讨论】:

标签: python string itertools


【解决方案1】:

您可以做的事情是使用字典理解构建字典并计算字典中每个条目中的值更改的次数:

d = {'a': ['+','+','-','-','+','-','-','+'], 'b': ['+','+','+','-','-','+','+','+','-'], 
     'c': ['-','-','-','+','+','+']}

s = {k : sum(1 for i,j in zip(d[k][1:], d[k][:-1]) if i != j) for k in d}
# {'a': 4, 'b': 3, 'c': 1}

或者如果你喜欢itertools.groupby:

{k : sum(1 for i in groupby(d[k]))-1 for k in d}
# {'a': 4, 'b': 3, 'c': 1}

详情

为了检测每个列表中元素的变化,您可以将其元素与列表的滞后版本进行比较,这可以通过压缩列表的两个切片来完成,zip(d[k][1:], d[k][:-1])。

例如,对于密钥a:

list(zip(d['a'][1:], d['a'][:-1]))
# [('+', '+'), ('-', '+'), ('-', '-'), ('+', '-'), ('-', '+'), ('-', '-'), ('+', '-')]

现在只需使用生成器表达式并在每次元组中的值不同时添加1:

sum(1 for i,j in zip(d['a'][1:], d['a'][:-1]) if i != j)
# 4

【讨论】:

  • 作为对 OP 的说明,d[k][1:], d[k][:-1] 将两个列表偏移了一个,因此您可以进行逐元素比较,而不是存储最后一个值并检查
  • 很棒的 yatu,谢谢,已经投票了,但我收到一些关于新用户的投票没有可视化或类似的信息。
  • 是的@fcalles,我认为你需要 15 个代表才能投票。不过不要忘记接受:-)。您可以通过投票勾选下的支票接受,请参阅What should I do when someone answers my question?
  • @fcalles 你现在也可以和你的代表一起投票 :-) (感谢接受!)
【解决方案2】:

您不需要过滤。只计算groupby:

mydict = {'a': ['+','+','-','-','+','-','-','+'],
'b': ['+','+','+','-','-','+','+','+','-'],
'c': ['-','-','-','+','+','+']}

for k,v in mydict.items():
  print(k + ' ' + str(len(list(itertools.groupby(list(v))))-1))

【讨论】:

  • 不需要list(v)
猜你喜欢
  • 2014-10-04
  • 2015-10-17
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多