如何在字符串中重复数字?

时间:2015-06-16 09:29:43

标签: regex tcl

我想获得字符串中重复特定数字的次数? 考虑数字是2,如果22在sting中可用,我们不应该考虑重复数字。

set a "1232163122631261112312"

在那个2中重复5次(我们不应该把22重复2次重复2次),我想通过使用正则表达式得到这个信息。

3 个答案:

答案 0 :(得分:1)

在循环中逐个字符扫描字符串可能会更快,但如果你坚持使用正则表达式:

对于数字2+的特定示例,您应使用的正则表达式为2(=数字1+的一倍或多倍)。然后你可以计算一个循环中的匹配数。

如果您希望其他数字相同,请复制该流程(使用3+,{{1}}等...)

答案 1 :(得分:1)

最紧凑的方式可能是:

string length [regsub -all {[^2]+|2{2,}} $a {}]

但还有更多内容。

测量列表中项目的频率非常简单:

set freq {}
foreach item $list {dict incr freq $item}

生成的字典将包含键及其频率的项目作为值。

如果您只想知道字符串中有多少'2',您可以使用该方法(split $a {}将字符串a转换为其组成字符列表):

set freq {}
foreach item [split $a {}] {dict incr freq $item}
dict get $freq 2

但是在这种情况下不起作用,因为你需要取消两个或更多相邻'2'的出现。解决这个问题的一种方法是在测量频率之前删除有问题的事件:

set freq {}
set b [regsub -all {2{2,}} $a {}]
foreach item [split $b {}] {dict incr freq $item}
dict get $freq 2

另一种方法是抛弃任何不是你想要的东西,然后计算你剩下的东西。在这种情况下,您寻找的是1)不是'2'([^2]+)的连续数字组,以及2)多个连续数字的组 '2'(2{2,}),导致正则表达式[^2]+|2{2,}

set b [regsub -all {[^2]+|2{2,}} $a {}]
string length $b

您也可以让regexp命令将字符串拆分为'2'组,然后使用拒绝过滤操作取出多个数字的组(可以方便地将其视为大于由一个数字组成的整数):

set b [regexp -inline -all {2+} $a]
# -> 2 2 22 2 2 2
set c [lmap item $b {if {$item > 2} continue {set item}}]
# -> 2 2 2 2 2
llength $c
# -> 5

或两个嵌套regexp s,外部删除所有包含多个字符的单词:

set b [regexp -inline -all {\m.\M} [regexp -inline -all {2+} $a]]
# -> 2 2 2 2 2
llength $b
# -> 5

或者您可以使用一些其他方法组合,可能折叠成单个命令而不是连续命令,其中保持变量将一个命令的结果传递给下一个命令:

llength [lmap item [regsub -all {[^2]+} $a { }] {if {$item > 2} continue {set item}}]

这个用空格替换所有不是'2'的数字,留下一个字符串,该字符串也是一个或多个'2'的组的列表。然后,该列表将通过上面的拒绝过滤器传递。

或者这个怎​​么样:

set b [regsub -all {[^2]+|2{2,}} $a 0]
set c [string map {2 1} $b]
expr [join [split $c {}] +]
# or
::tcl::mathop::+ {*}[split $c {}]

通过将违规组替换为0,然后将'2'替换为1,然后将字符串拆分为列表并在每个数字之间重新加入+字符,并将它们与expr相加,或者通过传递通过将$c拆分为::tcl::mathop::+命令获得的列表中的每个项目。

文档:continuedictforeachifjoinllengthlmap,{{3 }},mathopregexpregsubsetsplit

答案 2 :(得分:0)

如果必须通过正则表达式进行,可以尝试

(?:^|[^2])(2)(?!2)

并计算群组数量。但这可能无法扩展。请参阅演示。

https://regex101.com/r/rJ7hJ6/4

相关问题