我有一些工作代码来跟踪列表元素之间的“变化”-使得任何两个不相同的连续元素构成一个变化。此处的代码很容易理解。
testlist = ['red','red','blue','red','red','black','yellow','black','yellow','blue']
第一个red
至red
不会触发任何更改,但是下一个red
至blue
则会触发更改。 我也想对每种颜色进行汇总。
# Set Tally counters to 0 and a unique key
red = 0
blue = 0
black = 0
yellow = 0
key = 40006
for i in range(len(testlist)-1):
if (testlist[i] == (testlist[i+1])):
print("No Change")
else:
print("Change to: " + str(testlist[i+1]))
if testlist[i+1] == 'red':
red = red + 1
elif testlist[i+1] == 'blue':
blue = blue + 1
elif testlist[i+1] == 'black':
black = black + 1
elif testlist[i+1] == 'yellow':
yellow = yellow + 1
dictfordf = {'key':key, 'red':red,'blue':blue,'black':black,'yellow':yellow}
这有效并正确输出{'black': 2, 'blue': 2, 'key': 40006, 'red': 1, 'yellow': 2}
。
当唯一元素的数量增加(此示例中只有4种唯一颜色)到10时,if/elif
变得非常冗长。
我的两个问题是:
答案 0 :(得分:4)
首先,由于您的目标是构建一个dict,所以只需动态构建该dict,而不是构建一堆单独的变量,然后将其放在dict的最后即可。
您也可以使用Counter而不是普通字典,这样就不必担心检查颜色是否已经存在。
我们正在使用它,不需要在已经是字符串的东西上调用str
,并且到处都有很多不必要的括号。
所以:
from collections import Counter
dictfordf = Counter()
dictfordf['key'] = 40006
for i in range(len(testlist)-1):
if testlist[i] == testlist[i+1]:
print("No Change")
else:
print("Change to: " + testlist[i+1])
dictfordf[testlist[i+1]] += 1
存储'key'
的值确实不算是一个小事,所以您可能要考虑使用defaultdict
或{{1 }}来代替普通字典。但我认为这还不错。
当然,如果setdefault
可能是'key'
中的元素之一,那么这将使密钥递增。但是,如果可能的话,尚不清楚在这种情况下应该发生什么 ,因此也不清楚您要如何解决它。
同时,您可以通过迭代相邻对来使事情变得简洁。请参阅itertools
文档中的testlist
食谱。但是,当然,这会将pairwise
的定义添加到您的代码中(或者您可以从pairwise
或more-itertools
之类的第三方库中导入它。)
所以:
toolz
您可以使用from collections import Counter
from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
dictfordf = Counter()
dictfordf['key'] = 40006
for prev, current in pairwise(testlist):
if prev == current:
print("No Change")
else:
print("Change to: " + current)
dictfordf[current] += 1
或groupby
中的unique_justseen
配方进一步抽象事物。我认为这会掩盖而不是澄清您在itertools
的输出位置,但是,假设您了解print
的版本,则有必要对它们进行阅读,并尝试编写两种选择,至少锻炼。
答案 1 :(得分:1)
我对这个问题的看法:
from collections import Counter
testlist = ['red','red','blue','red','red','black','yellow','black','yellow','blue']
def changes(data):
last = data[0]
for i in data:
if last != i:
yield i
last = i
c = Counter(changes(testlist))
c['key'] = 40006
print(dict(c))
输出:
{'yellow': 2, 'red': 1, 'key': 40006, 'blue': 2, 'black': 2}
答案 2 :(得分:0)
我的拍摄使用zip
成对浏览列表,非常简洁。像其他人一样,它使用Counter
,我同意这是工作的正确工具。
from collections import Counter
testlist = ['red','red','blue','red','red','black','yellow','black','yellow','blue']
def count_changes(data):
c = Counter()
c['key'] = 40006
for item1, item2 in zip(data, data[1:]):
if item1 != item2:
c[item2] += 1
return c
print(count_changes(testlist))
输出:
Counter({'key': 40006, 'blue': 2, 'black': 2, 'yellow': 2, 'red': 1})
尚不清楚如果"key"
出现在测试列表中应该是什么正确的行为,但是直接修改此代码来处理它应该很简单。