8

文字列のリストがあるとしましょう:

a = ['a', 'a', 'b', 'c', 'c', 'c', 'd']

少なくとも2回続けて表示されるアイテムのリストを作成したい:

result = ['a', 'c']

forループを使用する必要があることはわかっていますが、連続して繰り返されるアイテムをターゲットにする方法がわかりません。どうすればいいですか?

編集:同じアイテムがで2回繰り返される場合はどうなりますか?その場合、集合関数は無効になります

a = ['a', 'b', 'a', 'a', 'c', 'a', 'a', 'a', 'd', 'd']
result = ['a', 'a', 'd']
4

9 に答える 9

7

ここで試しitertools.groupby()てください:

>>> from itertools import groupby,islice
>>> a = ['a', 'a', 'b', 'c', 'c', 'c', 'b']

>>> [list(g) for k,g in groupby(a)]
[['a', 'a'], ['b'], ['c', 'c', 'c'], ['b']] 

>>> [k for k,g in groupby(a) if len(list(g))>=2]
['a', 'c']

使用islice()

>>> [k for k,g in groupby(a) if len(list(islice(g,0,2)))==2]
>>> ['a', 'c']

とを使用zip()してizip()

In [198]: set(x[0] for x in izip(a,a[1:]) if x[0]==x[1])
Out[198]: set(['a', 'c'])

In [199]: set(x[0] for x in zip(a,a[1:]) if x[0]==x[1])
Out[199]: set(['a', 'c'])

timeit結果:

from itertools import *

a='aaaabbbccccddddefgggghhhhhiiiiiijjjkkklllmnooooooppppppppqqqqqqsssstuuvv'

def grp_isl():
    [k for k,g in groupby(a) if len(list(islice(g,0,2)))==2]

def grpby():
    [k for k,g in groupby(a) if len(list(g))>=2]

def chn():
    set(x[1] for x in chain(izip(*([iter(a)] * 2)), izip(*([iter(a[1:])] * 2))) if x[0] == x[1])

def dread():
    set(a[i] for i in range(1, len(a)) if a[i] == a[i-1])

def xdread():
    set(a[i] for i in xrange(1, len(a)) if a[i] == a[i-1])

def inrow():
    inRow = []
    last = None
    for x in a:
        if last == x and (len(inRow) == 0 or inRow[-1] != x):
            inRow.append(last)
        last = x

def zipp():
    set(x[0] for x in zip(a,a[1:]) if x[0]==x[1])

def izipp():
    set(x[0] for x in izip(a,a[1:]) if x[0]==x[1])

if __name__=="__main__":
    import timeit
    print "islice",timeit.timeit("grp_isl()", setup="from __main__ import grp_isl")
    print "grpby",timeit.timeit("grpby()", setup="from __main__ import grpby")
    print "dread",timeit.timeit("dread()", setup="from __main__ import dread")
    print "xdread",timeit.timeit("xdread()", setup="from __main__ import xdread")
    print "chain",timeit.timeit("chn()", setup="from __main__ import chn")
    print "inrow",timeit.timeit("inrow()", setup="from __main__ import inrow")
    print "zip",timeit.timeit("zipp()", setup="from __main__ import zipp")
    print "izip",timeit.timeit("izipp()", setup="from __main__ import izipp")

出力:

islice 39.9123107277
grpby 30.1204478987
dread 17.8041124706
xdread 15.3691785568
chain 17.4777339702
inrow 11.8577565327           
zip 16.6348844045
izip 15.1468557105

結論:

Pokeのソリューションは、他の選択肢と比較して最速のソリューションです。

于 2012-10-22T22:13:13.763 に答える
5

これは宿題のように聞こえるので、私が何をするかを概説します。

  1. を繰り返しaますが、各要素のインデックスを変数に保持します。enumerate()便利になります。
  2. ループ内で、現在のアイテムのインデックスからforループを開始します。while
  3. 次の要素が前の要素(または元の要素)と同じである限り、ループを繰り返します。breakここで役に立ちます。
  4. ループが繰り返される回数を数えます(これにはカウンター変数が必要です)。
  5. resultカウンター変数が>=2の場合、アイテムをに追加します。
于 2012-10-22T22:13:59.223 に答える
3

私の見解:

>>> a = ['a', 'a', 'b', 'c', 'c', 'c', 'd']
>>> inRow = []
>>> last = None
>>> for x in a:
        if last == x and (len(inRow) == 0 or inRow[-1] != x):
            inRow.append(last)
        last = x
>>> inRow
['a', 'c']
于 2012-10-22T22:20:05.820 に答える
3

どうですか:

set([a[i] for i in range(1, len(a)) if a[i] == a[i-1]])

于 2012-10-22T23:12:29.590 に答える
2

これが、私が望むことを実行するPythonワンライナーです。itertoolsパッケージを使用します:

from itertools import chain, izip

a = "aabbbdeefggh" 

set(x[1] for x in chain(izip(*([iter(a)] * 2)), izip(*([iter(a[1:])] * 2))) if x[0] == x[1])
于 2012-10-22T22:39:17.530 に答える
1

編集された質問は、set()を避けて、ほとんどの回答を除外するように求めています。

派手なワンライナーリスト内包表記を、@pokeや私が作成した別の古き良きループと比較すると思いました。

from itertools import *

a = 'aaaabbbccccaaaaefgggghhhhhiiiiiijjjkkklllmnooooooaaaaaaaaqqqqqqsssstuuvv'

def izipp():
    return set(x[0] for x in izip(a, a[1:]) if x[0] == x[1])

def grpby():
    return [k for k,g in groupby(a) if len(list(g))>=2]

def poke():
    inRow = []
    last = None
    for x in a:
        if last == x and (len(inRow) == 0 or inRow[-1] != x):
            inRow.append(last)
        last = x
    return inRow    

def dread2():
    repeated_chars = []
    previous_char = ''
    for char in a:
        if repeated_chars and char == repeated_chars[-1]:
            continue
        if char == previous_char:
            repeated_chars.append(char)
        else:
            previous_char = char
    return repeated_chars

if __name__=="__main__":
    import timeit
    print "izip",timeit.timeit("izipp()", setup="from __main__ import izipp"),''.join(izipp())
    print "grpby",timeit.timeit("grpby()", setup="from __main__ import grpby"),''.join(grpby())
    print "poke",timeit.timeit("poke()", setup="from __main__ import poke"),''.join(poke())
    print "dread2",timeit.timeit("dread2()", setup="from __main__ import dread2"),''.join(dread2())

結果が出ます:

izip 13.2173779011 acbgihkjloqsuv
grpby 18.1190848351 abcaghijkloaqsuv
poke 11.8500328064 abcaghijkloaqsuv
dread2 9.0088801384 abcaghijkloaqsuv

したがって、基本的なループは、すべてのリスト内包表記よりも高速であり、グループ化の2倍の速度であるように見えます。ただし、基本的なループは読み取りと書き込みがより複雑であるため、ほとんどの状況でgroupby()を使用することになります。

于 2012-10-23T13:39:33.757 に答える
0

正規表現のワンライナーは次のとおりです。

>>> mylist = ['a', 'a', 'b', 'c', 'c', 'c', 'd', 'a', 'a']
>>> results = [match[0][0] for match in re.findall(r'((\w)\2{1,})', ''.join(mylist))]
>>> results
['a', 'c', 'a']

申し訳ありませんが、時間を計るのが面倒です。

于 2012-10-23T19:25:26.323 に答える
0
a = ['a', 'a', 'b', 'c', 'c', 'c', 'd']
res=[]
for i in a:
    if a.count(i)>1 and i not in res:
        res.append(i)
print(res)
于 2012-10-27T03:25:40.350 に答える
0

enumerateを使用して、2つ続けてチェックします。

def repetitives(long_list)
  repeaters = []
  for counter,item in enumerate(long_list):
    if item == long_list[counter-1] and item not in repeaters:
      repeaters.append(item)
 return repeaters
于 2013-08-11T19:36:17.023 に答える