19日に更新してた

アフィリエイトはないよ

python で list 中の連続する同じ数値の連続する回数を得る

内包表記多め。
数値の桁数を上げても表記をできるだけ同じようにしようとすると、文字列操作するのが一番楽そうだったので文字列操作を使っております。

listに含まれる数値が0,1の場合

1が何回連続するか知りたい場合
import random

a=random.choices([0,1],k=15)

# 一塊の文字列にまとめます
b="".join([str(s) for s in a])

# 区切り文字として"0"を使い分割した文字列の文字数を出す、空の文字列は省く
c=[len(list(l)) for l in b.split("0") if l!=""]

a,b,c,max(c)

>>[0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1]
>> '011011011100111'
>> [2, 2, 3, 3],
>> 3
0が何回連続するか知りたい場合

a,bは上に同じ

#区切り文字として"1"を使い分割した文字列の文字数を出す、空の文字列は省く
d=[len(list(l)) for l in b.split("1") if l!=""]

a,b,d,max(d)

>>[0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1]
>>'011011011100111'
>>[1, 1, 1, 2]
>>2

listに含まれる数字が10未満の場合


桁数が一桁なので int から str の変換して使う。

特定値が何回連続するかを知りたい場合


この場合の特定値は0。

import random
a=random.choices(list(range(10)),k=20)

# 0の連続する回数を知りたい
select_number=0

# リスト内で隣り合う内容が異なる場合に str に変換した時に改行文字を加え、一塊の文字列にします
c="".join([str(j) if (i==len(a)-1 or a[i]==a[i+1]) else str(j)+"\n" for i,j in enumerate(a)])

# 改行文字で区切って、連続する回数が知りたい数値が含まれている内容を再度分割して、回数を得る
d=[len(list(k)) for k in c.split() if str(select_number) in k]

a,c,d

>>[7, 4, 3, 5, 0, 9, 2, 8, 6, 2, 0, 1, 3, 7, 3, 4, 0, 0, 0, 6]
>>'7\n4\n3\n5\n0\n9\n2\n8\n6\n2\n0\n1\n3\n7\n3\n4\n000\n6'
>>[1, 1, 3]
数値は関係なく連続している回数を知りたい場合


a,cは上に同じ。d の if 節をなくしただけですね。

# split()で区切っています
d=[len(list(s)) for s in c.split()]

a,c,d

>>[7, 4, 3, 5, 0, 9, 2, 8, 6, 2, 0, 1, 3, 7, 3, 4, 0, 0, 0, 6]
>>'7\n4\n3\n5\n0\n9\n2\n8\n6\n2\n0\n1\n3\n7\n3\n4\n000\n6'
>>[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1]

listに含まれる数値が自然数である場合


16進数に変換してます。

特定値が何回連続するかを知りたい場合
import random
a=random.choices(list(range(2600,2604)),k=15)

# 2603の連続する回数を知りたい
select_number=2603

# 16進数に変換して、隣り合う数値が異なる場合に改行文字を挿入し、一塊の文字列に変換
c="".join([str(hex(j)) if (i==len(a)-1 or a[i]==a[i+1]) else str(hex(j))+"\n" for i,j in enumerate(a)])

# 改行文字で区切って、区切った文字列内に知りたい数値が含まれるかどうかを調べ、数値が含まれる場合にその文字列が何回含まれるかを調べ、その最大値を得る
d=[len([i for i in h.split("0x") if i!="" ] )for h in c.split() if str(hex(select_number)) in h]

a,c,hex(select_number),d

>>[2602,  2601,  2600,  2603,  2603,  2602,  2603,  2600,  2601,  2602,  2602,  2603,  2603,  2603,  2602]
>>'0xa2a\n0xa29\n0xa28\n0xa2b0xa2b\n0xa2a\n0xa2b\n0xa28\n0xa29\n0xa2a0xa2a\n0xa2b0xa2b0xa2b\n0xa2a'
>>'0xa2b'
>>[2, 1, 3]
数値は関係なく連続している回数を知りたい場合


a,cは上に同じ。これも d の最後の if 節をなくしただけですが。

# 改行文字で区切った文字列から空の文字列を省き、"0x"で分割して、数値に変換して、数値の数を得る
d=[len([int(m,16) for m in l.split("0x") if m!=""]) for l in c.split()]

a,c,d

>>[2602,  2601,  2600,  2603,  2603,  2602,  2603,  2600,  2601,  2602,  2602,  2603,  2603,  2603,  2602]
>>'0xa2a\n0xa29\n0xa28\n0xa2b0xa2b\n0xa2a\n0xa2b\n0xa28\n0xa29\n0xa2a0xa2a\n0xa2b0xa2b0xa2b\n0xa2a'
>>[1, 1, 1, 2, 1, 1, 1, 1, 2, 3, 1]


ついでに、数字と数を照らし合わしたいなら

# どちらも基本同じで、内包表記が多重なのですが、timeit してみたらこんな感じ
[([int(m,16) for m in l.split("0x") if m!=""][0],len([int(m,16) for m in l.split("0x") if m!=""])) for l in c.split()]
#6.27 µs ± 133 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

[(n[0],len(n)) for n in [[int(m,16) for m in l.split("0x") if m!=""] for l in c.split()]]
#7.45 µs ± 182 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)


>>[(2602, 1), (2601, 1), (2600, 1), (2603, 2), (2602, 1), (2603, 1), (2600, 1), (2601, 1), (2602, 2), (2603, 3), (2602, 1)]


こんな感じですかね。思いつきを書きなぐってみました。