2

我在 stata 的宏中创建了一个手动列表,例如

global list1 "a b c d"

我后来用类似的东西迭代

foreach name in $list1 {
action
}

我正在尝试将其更改为数据库驱动列表,因为该列表变得越来越大并且变化迅速,我使用以下命令创建了一个新的 $list1

odbc load listitems=items, exec("SELECT items  from my_table")  
levelsof listitems
global list1=r(levels)

每个项目都相同,但这个列表似乎不同,当我有太多项目时,它会在 for 循环中中断并出现错误

{ required
r(100);

另外,当我只运行levelsof listitems时,我得到了输出

`"a"' `"b"' `"c"' `"d"' 

这看起来与其他宏有点不同。

我已经被困了一段时间了。同样,它仅在项目数量变大(超过 15 个)时才会失败,非常感谢任何帮助。

4

1 回答 1

7

解决方案1:

levelsof listitems, clean local(list1)
foreach name of local list1 {
    ...action with `name'...
}

解决方案2:

levelsof listitems, clean
global list1 `r(levels)'
foreach name of global list1 {
    ...action with `name'...
}

解释:

当您键入

foreach name in $list1 {

然后 $list1 中的任何内容都会在 Stata 看到它之前被内联替换。如果全局宏 list1 包含很长的事物列表,那么 Stata 会看到

foreach name in a b c d e .... very long list of things here ... {

告诉 Stata 你有一个全局或本地宏中的事物列表,并且你想循环这些事物会更有效。您不必在命令行上展开它们。那是什么

foreach name of local list1 {

foreach name of global list1 {

是给。您可以在 -help foreach- 中了解 foreach 的其他功能。

此外,您最初编码

levelsof listitems
global list1=r(levels)

你注意到你看到了

`"a"' `"b"' `"c"' ...

因此。这些就是 Stata 所说的“复合引用”字符串。复合引号字符串可让您有效地嵌套引用的内容。所以,你可以有类似的东西

`"This is a string with `"another quoted string"' inside it"'

你说你不需要那个,所以你可以使用levelsof的“clean”选项来不引用结果。(有关此选项的更多信息,请参见 -help levelsof-。)此外,您随后将 levelof(位于 r(levels) 中)的返回结果分配给全局宏。事实证明 -levelsof- 实际上有一个名为 -local()- 的选项,您可以在其中指定本地(非全局)宏的名称以直接放入结果。因此,您只需键入

levelsof listitems, clean local(list1)

既可以省略复合引号,也可以直接将结果放入名为 list1 的本地宏中。

最后,如果您出于某种原因不想使用该 local() 选项并希望坚持将您的列表放在全局宏中,您应该编写代码

global list1 `r(levels)'

而不是

global list1=r(levels)

区别在于后者将 r(levels) 视为一个函数并通过 Stata 的字符串表达式解析器运行它。在 Stata 中,字符串(字符串,不是包含字符串的宏)有 244 个字符的限制。另一方面,包含字符串的宏可以包含数千个字符。因此,如果 r(levels) 中有超过 244 个字符,那么

global list1=r(levels)

最终会截断存储在 list1 中的 244 个字符的结果。

当您改为编码时

global list1 `r(levels)'

然后 r(levels) 的内容在执行命令之前内联展开。所以,Stata 看到

global list1 a b c d e ... very long list ... x y z

并且宏名称 (list1) 之后的所有内容都被复制到该宏名称中,无论它有多长。

于 2011-06-21T18:09:46.947 回答