列表python中的计数列表出现次数
我想数一数一个大列表中按特定顺序包含元素的次数。例如,如果我有元素列表python中的计数列表出现次数,python,Python,我想数一数一个大列表中按特定顺序包含元素的次数。例如,如果我有元素[1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5],我想知道有多少次[1,2,3]彼此相邻(在这种情况下,答案是4) 我正在考虑检查数字“3”的索引(因此当前它将返回[2,7,12,17]。然后我会迭代该列表,在列表中描述的位置获取元素,并检查前面的两个位置。如果它们与“1”和“2”匹配,则添加1到计数器并继续查找。我相信此解决方案效率不高,也不好看,是否有更好的解决方案?对于int列表,您可以转换
[1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
,我想知道有多少次[1,2,3]
彼此相邻(在这种情况下,答案是4
)
我正在考虑检查数字“3”的索引(因此当前它将返回
[2,7,12,17]
。然后我会迭代该列表,在列表中描述的位置获取元素,并检查前面的两个位置。如果它们与“1”和“2”匹配,则添加1到计数器并继续查找。我相信此解决方案效率不高,也不好看,是否有更好的解决方案?对于int列表,您可以转换创建字符串,然后使用计数方法:
>>> x = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
>>> y = [1,2,3]
>>> s = ',' + ','.join(str(i) for i in x) + ','
>>> t = ',' + ','.join(str(i) for i in y) + ','
>>> s.count(t)
4
如果列表中的项包含包含逗号的字符串,则此方法可能会失败(正如@schwobasegll在注释中指出的)。您需要选择一个已知不会出现在任何字符串中的分隔符,或者采用一种完全不同的方法,该方法不会减少到stringcount
方法
编辑时:我添加了@Rawing建议的修复程序,以解决@tobias_k指出的一个错误。这是一个比最初看起来更微妙的问题。您可以迭代列表并比较子列表:
In [1]: lst = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
In [2]: sub = [1,2,3]
In [3]: [i for i, _ in enumerate(lst) if lst[i:i+len(sub)] == sub]
Out[3]: [0, 5, 10, 15]
但是,请注意,在一个非常大的列表和子列表上,这是非常浪费的,因为它会创建许多原始列表的切片来与子列表进行比较。在稍长的版本中,您可以使用all
将列表的每个相关位置与子列表的位置进行比较:
In [5]: [i for i, _ in enumerate(lst) if all(lst[i+k] == e for k, e in enumerate(sub))]
Out[5]: [0, 5, 10, 15]
这是一个通用的解决方案,适用于任何大小的子序列和任何类型的元素。它也非常节省空间,因为它只在迭代器上运行
from itertools import islice
def count(lst, seq):
it = zip(*(islice(lst, i, None) for i in range(len(seq))))
seq = tuple(seq)
return sum(x == seq for x in it)
其思想是在lst
上创建宽度len(seq)
的滑动窗口迭代器,并计算等于tuple(seq)
的元组数。这意味着count
也计算重叠匹配:
In [5]: count('aaa', 'aa')
Out[5]: 2
我觉得这是最长的常见子序列问题,每次都会重复,直到返回的序列是一个空列表 我认为在这种情况下,对于一个有效的算法,你能做的最好的事情是O(n*m),其中n是你的大列表中的元素数,m是你的小列表中的元素数。当然,你必须有一个额外的步骤,从大序列中删除小序列并重复这个过程 以下是算法:
def lcs(first, second):
results = dict()
return lcs_mem(first, second, results)
def lcs_mem(first, second, results):
key = ""
if first > second:
key = first + "," + second
else:
key = second + "," + first
if len(first) == 0 or len(second) == 0:
return ''
elif key in results:
return results[key]
elif first[-1] == second[-1]:
result = lcs(first[:-1], second[:-1]) + first[-1]
results[key] = result
return result
else:
lcsLeft = lcs(first[:-1], second)
lcsRight = lcs(first, second[:-1])
if len(lcsLeft) > len(lcsRight):
return lcsLeft
else:
return lcsRight
def main():
pass
if __name__ == '__main__':
main()
请随意修改以上算法。可以从复杂性定义解决方案的效率。在谷歌搜索更多关于算法复杂性的信息
x = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
y = [1,2,3]
count = 0
for i in range(len(x)-len(y)):
if x[i:i+len(y)] == y:
count += 1
print(count)
在你们的例子中,复杂性是2n,其中n是元素的数量
这是复杂度为n的解决方案,因为它只遍历列表一次,即n次
def IsSameError(x,y):
if (len(x) != len(y)):
return False
i = 0
while (i < len(y)):
if(x[i] != y[i]):
return False
i += 1
return True
x = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
y = [1, 2, 3]
xLength = len(x)
yLength = len(y)
cnt = 0
answer = []
while (cnt+3 < xLength):
if(IsSameError([x[cnt], x[cnt+1], x[cnt+2]], y)):
answer.append(x[cnt])
answer.append(x[cnt+1])
answer.append(x[cnt + 2])
cnt = cnt + 3
else:
cnt = cnt + 1
print answer
def ISSAMERROR(x,y):
如果(len(x)!=len(y)):
返回错误
i=0
而(i
旋转[12,3]
和[1,23]
进入同一个实体。如果我的列表有约600万个元素,它会在正常时间运行吗?@schwobasegll我从未声称我的解决方案是计算任意子列表的通用方法。这是一种完全足够的快速和肮脏的方法,可以覆盖大多数情况,包括问题中的示例。不过,你提出了一个很好的解决方案要点。在字符串列表的情况下,必须注意分隔符的选择。即使对于int
列表,如果搜索模式为1,2,3
,并且列表包含例如11,2,33
@JohnColeman,这也不是一个致命的问题。您只需要在st的开头和结尾加逗号即可戒指。由于OP的列表似乎有约600万个元素,使用islice
@Rawing可能是一个好主意。是的,同意。它可能有较低的复杂性,但很难说没有基准测试它会更好。我的推理是在Python中,循环以c级速度运行,而循环则不以c级速度运行。这意味着使用Python中的for循环速度更快。同样,您正在使用附加程序创建内存分配,这也是一个繁重的过程。因此,在这种情况下,复杂度的折衷可能不值得。我不知道for循环和while循环之间的区别。请您给出慢的原因。如果您将我的答案与另一个答案是,我可以跳过附加部分,我们也可以用for循环替换while循环。但是,是的,知识非常丰富。你也需要计算重叠匹配吗?例如,[1,1]
包含在[1,1,1]
中多少次?不,在我的情况下没有重叠匹配。
def IsSameError(x,y):
if (len(x) != len(y)):
return False
i = 0
while (i < len(y)):
if(x[i] != y[i]):
return False
i += 1
return True
x = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
y = [1, 2, 3]
xLength = len(x)
yLength = len(y)
cnt = 0
answer = []
while (cnt+3 < xLength):
if(IsSameError([x[cnt], x[cnt+1], x[cnt+2]], y)):
answer.append(x[cnt])
answer.append(x[cnt+1])
answer.append(x[cnt + 2])
cnt = cnt + 3
else:
cnt = cnt + 1
print answer