找到第一个非零小数的位置

Ste*_*rdi 2 regex string stata

假设我有以下本地宏:

loc a = 12.000923
Run Code Online (Sandbox Code Playgroud)

我想获得第一个非零小数的小数位(4在本例中).

有很多方法可以实现这一目标.一种是a作为一个字符串处理并找到以下位置.:

loc a = 12.000923
loc b = strpos(string(`a'), ".")
di "`b'"
Run Code Online (Sandbox Code Playgroud)

从这里可以进一步循环小数并计数,因为我得到第一个非零元素.当然,这似乎不是一个非常优雅的方法.

你能建议一个更好的方法来解决这个问题吗?也许正则表达式?

Pea*_*cer 5

您可以mata在一行中执行此操作,无需使用正则表达式:

foreach x in 124.000923 65.020923 1.000022030 0.0090843 .00000425 {
    mata: selectindex(tokens(tokens(st_local("x"), ".")[selectindex(tokens(st_local("x"), ".") :== ".") + 1], "0") :!= "0")[1]
}

4
2
5
3
6
Run Code Online (Sandbox Code Playgroud)

下面,您可以看到详细步骤:

. local x = 124.000823

. mata:

: /* Step 1: break Stata's local macro x in tokens using . as a parsing char */
: a = tokens(st_local("x"), ".")

: a
            1        2        3
    +----------------------------+
  1 |     124        .   000823  |
    +----------------------------+

: /* Step 2: tokenize the string in a[1,3] using 0 as a parsing char */
: b = tokens(a[3], "0")

: b
         1     2     3     4
    +-------------------------+
  1 |    0     0     0   823  |
    +-------------------------+

: /* Step 3: find which values are different from zero */
: c = b :!= "0"

: c
       1   2   3   4
    +-----------------+
  1 |  0   0   0   1  |
    +-----------------+

: /* Step 4: find the first index position where this is true */
: d = selectindex(c :!= 0)[1]

: d
  4

: end
Run Code Online (Sandbox Code Playgroud)

您还可以2使用相同的逻辑在Step中找到感兴趣的字符串的位置.

这是以下之后的索引值.:

. mata: 

: k = selectindex(a :== ".") + 1

: k
  3

: end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Step 2变为:

. mata: 

: 
: b = tokens(a[k], "0")

: b
         1     2     3     4
    +-------------------------+
  1 |    0     0     0   823  |
    +-------------------------+

: end
Run Code Online (Sandbox Code Playgroud)

对于没有小数的意外情况:

foreach x in 124.000923 65.020923 1.000022030 12 0.0090843 .00000425 {
    if strmatch("`x'", "*.*") mata: selectindex(tokens(tokens(st_local("x"), ".")[selectindex(tokens(st_local("x"), ".") :== ".") + 1], "0") :!= "0")[1]
    else display "  0"
}

4
2
5
0
3
6
Run Code Online (Sandbox Code Playgroud)