|
[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]
Re: st: Using foreach and two local macros
On Aug 7, 2008, at 10:46 AM, Gawrich Stefan wrote:
Looping over parallel lists is indeed a very powerful feature. To
keep it flexible you'll often use a second extended function (word
count) with the forval command.
local x "1 2"
local y "3 4"
local n : word count `x'
forvalues i = 1/`n' {
local x1 : word `i' of `x'
local y1 : word `i' of `y'
di `x1'+2*`x1'+`y1'
}
But in my view the syntax has two drawbacks:
1) It needs a lot of lines. So it bloats your do-files expecially
when you use it with more than two locals. (I often use it for
batch graph creation where variables, selections, titles and
settings can make up to ten locals)
2) You have to create new local names inside the loop, which makes
it confusing and error prone
So sometimes I find it convenient to use that good old (not longer
documented) "for" command again.
<snip>
When you brought this up 2 years ago:
http://www.stata.com/statalist/archive/2006-03/msg00522.html
I pointed out that you can use nested lists as an alternative, and
Nick elaborated on that:
http://www.stata.com/statalist/archive/2006-03/msg00545.html
http://www.stata.com/statalist/archive/2006-03/msg00546.html
IMHO, nested lists are often a better approach. For example, consider
loc foo `" "1 a I" "2 b II" "3 c III" "'
foreach item of loc foo {
tokenize `"`item'"'
di "`1' `2' `3'"
}
versus
loc l1 1 2 3
loc l2 a b c
loc l3 I II III
for num `l1' \ any `l2' \ any `l3': di "X Y Z"
In the first case, when you construct the macro foo, you are keeping
the values 1, a, and I all together as a group, which is much less
prone to error than when you have to construct l1, l2, and l3
separately (e.g., the lengths may not match, you may get the ordering
of the sub-items messed up, etc.). Thus, if you are constructing
your list(s) by hand, I would argue that the former is much better
(and much easier to maintain if you have to add/drop parts of each
item in the list later on).
Now, if you are in the position where l1, l2, and l3 are generated
programmatically, you just need to assemble them into a nested list.
Python has a function for this called -zip()-:
>>> l1 = [1,2,3]
>>> l2 = ['a','b','c']
>>> l3 = ['I','II','III']
>>> zip(l1,l2,l3)
[(1, 'a', 'I'), (2, 'b', 'II'), (3, 'c', 'III')]
It would not be difficult to write a Mata function to do this;
alternatively, one could imagine StataCorp adding an extended macro
function (i.e., something like {local | global} macname : list zip
macnames).
-- Phil
*
* For searches and help try:
* http://www.stata.com/help.cgi?search
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/