识别重复列表项的运行

时间:2016-05-24 02:29:32

标签: python

我列表中有一系列项目。我想识别相同元素的运行并打印它们的起始位置和结束位置。例如,使用:

content=[c,c,c,c,f,f,f,f,c,c,b,b,b,b...]

我希望输出如下:

1-4 c
5-8 f
9-10 c

依此类推。这是我到目前为止所做的:

x=len(content)-1
i=0
y=0
z=0
for i in range(0,x):
  if(content[i]==content[i+1]):
    y=y+1
    z=i-1
  else:
    print y
    print content[z]

3 个答案:

答案 0 :(得分:1)

第一个不是您的ifelse,而是您如何循环。您似乎错过了对range的调用,并且只有调用的参数。尝试:

for i in range(0, x):

现在将到达ifelse块,您只需调整它们即可跟踪您关注的值。如果您想要开始和连续运行项目,您实际上并不需要这两个部分。试试这个:

run_start = 0
for i in range(len(content)-1):
    if content[i] != content[i+1]: # only one branch needed, nothing to do when items are ==
        print "{}-{} {}".format(run_start+1, i+1, content[i])
        run_start = i+1
print "{}-{} {}".format(run_start+1, len(content), content[-1]) # extra code for the last run

如果运行中只有一个项目,则会打印3-3之类的范围。如果您不想要,则可能需要添加另一个if语句来检查irun_start不相等(并打印其他内容,或跳过该运行如果他们是)。

我发现在可能的情况下,使用有意义的变量名称会非常有帮助。在这种情况下,我使用run_start而不是yx

答案 1 :(得分:1)

Blckknght的解决方案很棒。我自己的版本更加冗长,以防止您理解整个过程背后的逻辑。您需要做的是遍历列表中的每个元素并将其存储在current中,并将其与来自上一次迭代的last(最后一个已知对象)进行比较。如果它们相同,则递增range_end索引。如果它们不同,则表示新范围正在开始,因此您必须执行以下操作:

  • 打印到目前为止所学到的内容,至range_beginrange_endcurrent元素。
  • current元素存储在last中,因为它是新序列的第一个元素
  • 将范围索引range_beginrange_end设置为当前i

要使整个过程正常工作,您需要在循环到last列表的第一个元素之前初始化content

此外,由于索引i从0开始,当我们同时打印range_beginrange_end时,我们只会将它们增加1。

content=['c','c','c','c','f','f','f','f','c','c','b','b','b','b']
range_begin=0
range_end=0
last=content[0]  # store the first element as the last known
for i in range(0, len(content)):
  current = content[i]  # get the element from the list
  if last != current:   # compare to the last known, if different
    print "{}-{} {}".format(range_begin+1, range_end+1, last)  # print
    last = current      # store the current as last known
    range_begin = i     # reset the ranges to the current index
    range_end = i
  else:
    range_end = i       # if they are the same, just extend the range_end

同时检查: https://eval.in/575899

答案 2 :(得分:1)

您正在尝试解决一个非常重要的问题(如果还是相当简单),我建议您从标准库中获得帮助。 itertools模块提供groupby功能,几乎可以满足您的需求。给定一系列元素 x 1 ,..., x n 它将产生你对一个键 k 和一个非空的懒惰元素序列 g 进行配对( k g )比较等于 k 。 (您可以将 g 转换为普通列表,方法是将list应用到普通列表中。)

让我们试一试:

from itertools import groupby
items = "ccccffffccbbbb"
for (k, g) in groupby(items):
    print k, list(g)

输出:

c ['c', 'c', 'c', 'c']
f ['f', 'f', 'f', 'f']
c ['c', 'c']
b ['b', 'b', 'b', 'b']

这看起来已经非常有用,但我们必须从相等项目列表中计算开始和结束索引。幸运的是,我们知道第一组的开始索引 - 它是1.如果我们知道任何组的开始索引,我们也知道它的结束索引,即开始索引加上组的长度减去1.开始索引下一组的将是当前组的开始索引加上当前组的长度。

这就是我们所需要的:

from itertools import groupby
items = "ccccffffccbbbb"
offset = 1
for (k, g) in groupby(items):
    length = len(list(g))  # simple and does the job but not as efficient as it could be
    print '{}-{} {}'.format(offset, offset + length - 1, k)
    offset += length

输出:

1-4 c
5-8 f
9-10 c
11-14 b