如何获取字符串中重复的数字?
How to get repeated number in string?
我想获取特定数字在字符串中重复的次数?
考虑数字是2,如果22在sting中可用,我们不应该认为是重复数字。
set a "1232163122631261112312"
因为 2 重复了 5 次(我们不应该把 22 当作数字 2 的 2 次重复),我想通过正则表达式来获取这个信息。
如果你必须通过正则表达式来完成,你可以尝试
(?:^|[^2])(2)(?!2)
并计算 groups.But 的数量,这可能不是 scalable.See 演示。
在循环中逐字符扫描字符串可能会更快,但如果您坚持使用正则表达式:
对于数字 2
的特定示例,您应该使用的正则表达式是 2+
(= 数字 2
的一倍或更多倍)。然后你可以计算循环中的匹配数。
如果您希望对其他号码进行相同操作,请重复该过程(使用 1+
、3+
等...)
最紧凑的方式大概是:
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
,外层去掉所有超过一个字符的词:
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}}]
这个用 space 替换所有不是“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 替换有问题的组,然后用 1 替换 '2',然后将字符串拆分成一个列表并在每个数字之间用 + 字符重新加入它,然后用 expr
对它们求和,或者将拆分 $c
得到的列表中的每一项传递给 ::tcl::mathop::+
命令。
文档:continue, dict, foreach, if, join, llength, lmap, mathop, regexp, regsub, set, split, string
我想获取特定数字在字符串中重复的次数? 考虑数字是2,如果22在sting中可用,我们不应该认为是重复数字。
set a "1232163122631261112312"
因为 2 重复了 5 次(我们不应该把 22 当作数字 2 的 2 次重复),我想通过正则表达式来获取这个信息。
如果你必须通过正则表达式来完成,你可以尝试
(?:^|[^2])(2)(?!2)
并计算 groups.But 的数量,这可能不是 scalable.See 演示。
在循环中逐字符扫描字符串可能会更快,但如果您坚持使用正则表达式:
对于数字 2
的特定示例,您应该使用的正则表达式是 2+
(= 数字 2
的一倍或更多倍)。然后你可以计算循环中的匹配数。
如果您希望对其他号码进行相同操作,请重复该过程(使用 1+
、3+
等...)
最紧凑的方式大概是:
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
,外层去掉所有超过一个字符的词:
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}}]
这个用 space 替换所有不是“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 替换有问题的组,然后用 1 替换 '2',然后将字符串拆分成一个列表并在每个数字之间用 + 字符重新加入它,然后用 expr
对它们求和,或者将拆分 $c
得到的列表中的每一项传递给 ::tcl::mathop::+
命令。
文档:continue, dict, foreach, if, join, llength, lmap, mathop, regexp, regsub, set, split, string