Когда я использую цикл do для перебора массива слов в SAS и проверки их существования в строке, это работает. Когда я добавляю второй для ежедневных слов, FINDW не находит слова, уже находящиеся в конечной строке.
Итак, это работает так, как ожидалось:
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("-", str, word[i]);
Это дает мне ожидаемую окончательную строку «блинчик-пончик».
Однако, когда я включаю дни в дело (каждый день может быть несколько названий завтраков), findw начинает вести этот странный двойной счет. Данные выглядят так, они описывают продукты, которые мы ели на завтрак в данный день:
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 j=1 to 4 /*january 1st - january 4th*/;
do i=1 to i=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;
Это возвращает окончательный all_breakfast_foods «блин-пончик-блин», он дважды считает блин!!! Я понятия не имею, почему word_find не находит блин, когда он явно содержится в строке all_breakfast_foods.
Вот что происходит в цикле:
daily_breakfast_foods1 | daily_breakfast_foods2 |daily_breakfast_foods3 | daily_breakfast_foods4 | daily_breakfast_foods5 |
-----------------------|------------------------|-----------------------|-----------------------|------------------------|
| donut | |pancake | |```
@Tom хм... когда я меняю 5-ю строку в реальном примере на------------------------------------------------ ----------- то daily_breakfast_foods[i] = strip(scan(breakfast_foods[j], i, "-", "d")); это не решает проблему.
Исправление состояло в том, чтобы не раздеваться в строке 5, как я пытался. Мне пришлось добавить strip() в функцию findw в word_find в строке 8 как таковую:
word_find = findw(translate(all_breakfast_foods, " ", "-"), STRIP(daily_breakfast_foods[i]), " ");
Ооооочень странно.
Таким образом, в вашем списке есть несколько начальных пробелов (пробелы после разделителя -), которые вызывают проблемы. Вы можете использовать функцию LEFT() для удаления начальных пробелов. И FINDW() имеет модификатор T для обрезки конечных пробелов при поиске слов.
Итак, давайте превратим ваш список тестовых данных в реальный набор данных.
data have ;
input (breakfast_foods_jan1-breakfast_foods_jan4) ($40./);
cards;
breakfast-pancake
breakfast-donut-pancake
breakfast-donut-pancake
breakfast-donut- pancake
;
Теперь мы можем перебрать переменные еды, а затем перебрать каждый список продуктов и создать список уникальных продуктов.
data want;
set have;
array foods breakfast_foods_jan1-breakfast_foods_jan4 ;
length next_food $30 food_list $200 ;
do day=1 to dim(foods);
do item=1 to countw(foods[day],'-');
next_food = left(scan(foods[day],item,'-'));
if next_food ne 'breakfast' then do;
if not findw(food_list,next_food,'-','t') then
food_list=catx('-',food_list,next_food)
;
end;
end;
end;
drop day item next_food;
run;
Результат:
Спасибо! Это работает. Хорошо, но если сделать массив из отсканированных слов. SAS не покажет вам начальные пробелы в этих переменных! Так сложно устранить неполадки.
Как вы попросили SAS показать вам? Если вы распечатаете обычный текстовый список, вы увидите начальные пробелы. Но если вы печатаете в ODS, они «исчезают». Вы можете использовать формат $QUOTE с переменными для отображения значений внутри кавычек. Тогда ведущие пробелы более заметны. Также возможно, что ваши реальные данные имеют какой-то другой невидимый характер. В этом случае печать значений в формате $HEX покажет символы. '20'x - это пробел. '09'x - это табуляция.
Я не хотел приводить полный пример... строки содержат количество съеденных за день продуктов. (т.е. пончик-1-блин-1), отсюда и разделитель "d" в findw. Я вижу, как возможно, что появляются дополнительные пробелы. Я постараюсь использовать $QUOTE, чтобы избежать этого в будущем.
Просто ваш примерный список значений включает как «блин», так и «блин»? У второго есть ведущее место.