嵌套DO循环中SAS FINDW函数出现异常行为?
SAS嵌套DO循环中FINDW函数重复计数问题
问题现象
单个DO循环遍历单词数组并检查字符串中是否存在目标单词时,FINDW函数工作正常;但加入每日食物的第二层DO循环后,FINDW无法识别已存在于最终字符串中的单词,导致出现重复计数的问题。
单个循环正常示例
以下代码通过单个DO循环遍历单词数组,能够正确生成无重复的字符串:
word1=""; word2="pancake"; word3=""; word4="donut"; word5=""; array word {5} $ 250 word:; final_str="pancake"; do i = 1 to 5; final_str_w_removed_hyphens = translate(final_str, " ", "-"); if findw(final_str_w_removed_hyphens, word[i], " ") = 0 then final_str = catx("-", final_str, word[i]); end;
执行后返回预期结果:pancake-donut
多日早餐数据场景异常表现
数据示例
| breakfast_foods_jan1 | breakfast_foods_jan2 | breakfast_foods_jan3 | breakfast_foods_jan4 |
|---|---|---|---|
| "breakfast-pancake" | "breakfast-donut-breakfast-pancake" | "breakfast-donut-breakfast-pancake" | "breakfast-donut-breakfast-pancake" |
问题代码
为提取全年唯一早餐食物,编写嵌套DO循环代码如下:
do j=1 to 4 /*january 1st - january 4th*/; do i=1 to 5 /*there can't be more than 5 breakfast items on any day*/; if scan(breakfast_foods[j], i, "-", "d") ne "breakfast" then daily_breakfast_foods[i] = scan(breakfast_foods[j], i, "-", "d"); word_find = findw(translate(all_breakfast_foods, " ", "-"), daily_breakfast_foods[i], " "); if word_find=0 then all_breakfast_foods = catx("-", all_breakfast_foods, daily_breakfast_foods[i]); end; end;
执行后返回结果异常:pancake-donut-pancake,出现pancake重复的问题。
调试信息
daily_breakfast_foods数组值
| daily_breakfast_foods1 | daily_breakfast_foods2 | daily_breakfast_foods3 | daily_breakfast_foods4 | daily_breakfast_foods5 |
|---|---|---|---|---|
| donut | pancake |
all_breakfast_foods迭代过程
| all_breakfast_foods_debug1 | all_breakfast_foods_debug2 | all_breakfast_foods_debug3 | all_breakfast_foods_debug4 | all_breakfast_foods_debug5 |
|---|---|---|---|---|
| pancake | pancake | pancake donut | pancake donut | pancake donut pancake |
问题原因及解决方法
核心原因
- 数组未重置:
daily_breakfast_foods数组在每日循环(j循环)未被重置为空,导致前一天的旧值(如pancake)残留,后续循环中被重复处理; - 空格干扰:数组定义为$250长度,单词后存在大量 trailing spaces,导致FINDW匹配失败;
- 空值未过滤:未对
scan返回的空值做处理,无效元素进入判断逻辑。
解决代码
/* 初始化存储所有唯一早餐食物的变量 */ length all_breakfast_foods $ 1000; all_breakfast_foods = ""; array breakfast_foods[4] $ 250 breakfast_foods_jan1 breakfast_foods_jan2 breakfast_foods_jan3 breakfast_foods_jan4; array daily_breakfast_foods[5] $ 250; do j=1 to 4; /* 每日循环开始前重置数组为空 */ call missing(of daily_breakfast_foods[*]); do i=1 to 5; current_item = scan(breakfast_foods[j], i, "-", "d"); /* 跳过空值和"breakfast"关键词 */ if current_item ne "" and current_item ne "breakfast" then do; current_item = trim(current_item); /* 转换分隔符并使用去空格后的单词匹配 */ if findw(translate(all_breakfast_foods, " ", "-"), current_item, " ") = 0 then do; all_breakfast_foods = catx("-", all_breakfast_foods, current_item); end; end; end; end;
关键优化点
- 每次j循环前通过
call missing(of daily_breakfast_foods[*])重置数组,清除旧值; - 使用
trim()去除单词首尾空格,确保FINDW匹配准确; - 增加空值和关键词过滤,跳过无效元素处理。
内容的提问来源于stack exchange,提问作者brown twelve
相关产品推荐
相关产品推荐

