为了账号安全,请及时绑定邮箱和手机立即绑定

优化计数列表中元素之间的变化

优化计数列表中元素之间的变化

慕标琳琳 2021-04-15 14:15:17
我有一些工作代码来跟踪列表元素之间的“变化”-这样,任何两个不相同的连续元素都会构成一个变化。该代码在这里可能很容易理解。testlist = ['red','red','blue','red','red','black','yellow','black','yellow','blue']第一个red到red会触发没有变化,但是接下来red要blue会。我也想统计每种颜色的变化。# Set Tally counters to 0 and a unique keyred = 0blue = 0black = 0yellow = 0key = 40006for 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 + 1dictfordf = {'key':key, 'red':red,'blue':blue,'black':black,'yellow':yellow}这可以{'black': 2, 'blue': 2, 'key': 40006, 'red': 1, 'yellow': 2}正常工作并输出。当唯一元素的数量增加(在此示例中,仅4种唯一颜色)到10时,if/elif变得非常冗长。我的两个问题是:有没有更简洁的方法来实现这一目标?有没有更快的方法来执行此任务?
查看完整描述

3 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

我对这个问题的看法:


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}


查看完整回答
反对 回复 2021-04-27
?
慕沐林林

TA贡献2016条经验 获得超9个赞

我的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"出现在测试列表中,正确的行为应该是什么,但是修改此代码以解决该问题很简单。


查看完整回答
反对 回复 2021-04-27
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

首先,由于您的目标是构建一个dict,所以只需动态构建该dict,而不是构建一堆单独的变量,然后将它们放在dict的末尾即可。


您也可以使用Counter而不是Plain dict,因此您不必担心检查颜色是否已经存在。


当我们使用它时,不需要调用str已经是字符串的东西,并且到处都有很多不必要的parens。


所以:


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,或setdefault在普通字典,来代替。但我认为这并不算太糟。


当然,如果'key'可能是中的元素之一,则将testlist增加密钥。不过,如果这是可能的,目前还不清楚是什么应该在这种情况下发生的,所以目前还不清楚你要如何解决它。


同时,您可以通过遍历相邻对来简化事情。请参阅文档中的pairwise食谱itertools。但是,当然这会在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的输出结果,但是,假设您了解pairwise版本,则值得阅读它们的两个部分,并至少在练习中尝试编写这两种选择。


查看完整回答
反对 回复 2021-04-27
  • 3 回答
  • 0 关注
  • 205 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号