Trouble while playing with squiffy.story.go loops

I think this is supposed to work. I can get it to loop and print a lexicon of all the words in the string, but then it won't go to the next section.

@start foods

[[foods]]:
@inc loops
    var loops = squiffy.get("loops");
    let food = "For breakfast, I had leftover chicken. For lunch, I had more leftover chicken.";
    var indivWords = food.split(' ').length;
    var word = food.split(' ')[loops];
    var word = word.replace(/[.,]/g, "");
    var wordInstances = new RegExp(word, "g");
    var count = food.match(wordInstances).length;
    squiffy.set(word, count);
    if (indivWords != loops){squiffy.story.go("foods")} //I can phrase this conditional in a bunch of ways and it always works.
    else {squiffy.story.go("nutrition facts")}; //So why won't this ELSE work?


[[nutrition facts]]:
 Will I ever get into this section?

You're off by one.

If indivWords is 13, there are 13 words in the string, numbered from 0 to 12. So when loops is 13, it gets as far as the line: var word = food.split(' ')[loops];. This causes an error, because there isn't a word number 13. And because it's had an error, it doesn't get to the if statement at the end of the script.

I suspect that you want to change it to var word = food.split(' ')[loops-1]; - that way, the first time through the script (when loops is 1, it will look at word 0, the first word. And the last time through the loop, when loops is 13 (or whatever the number of words is) it will look at word number 12 (the last one).


Also, I guess you're going about this in an unusual way for some reason, but not sure what it could be. Is there some reason you need to keep going back to the same section?
(Edit… made a silly mistake)

It seems like you could achieve the same effect with considerably less code:

[[foods]]:
    let food = "For breakfast, I had leftover chicken. For lunch, I had more leftover chicken.";
    let wordsfound = {};
    food.split(" ").forEach(word => squiffy.set(word, ++wordsfound[word.replace(/[,.]/g, "")]));
    squiffy.story.go("nutrition facts");

Thanks, mrangel. The first time I ever asked for help on this forum, Alex Warren gave me a solution in jQuery, evidently. I had little understanding of how it worked, but I pasted it into several projects. I'm now just beginning to learn how to write verbose js commands and actually know what they're telling the browser to do. I'm also still heavily relying on Squiffy's abilities, and making basic mistakes.


Actually, I realised later that my solution and your solution aren't quite the same. Mine counts the number of times each word appears in the sentence; yours loops over the words and counts the number of times each of them appears. Not sure if that's intentional behaviour or not.

The difference is that if the sentence included a short word like "a", mine would count the number of times "a" appears as a word; while yours would count the number of times the letter "a" appears, including within other words.

So if I was trying to replicate what your code actually does, I should have done:

[[foods]]:
    let food = "For breakfast, I had leftover chicken. For lunch, I had more leftover chicken.";
    food.split(" ").forEach(word => squiffy.set(word, food.match(new RegExp(word.replace(/[,.]/g, ""), "g"))));
    squiffy.story.go("nutrition facts");

Or to keep track of which words you already counted, so it doesn't run more than once.

[[foods]]:
    let food = "For breakfast, I had leftover chicken. For lunch, I had more leftover chicken.";
    let wordsfound = {};
    food.split(" ").forEach(word => wordsFound[word] ||= squiffy.set(word, food.match(new RegExp(word.replace(/[,.]/g, ""), "g")) || 1));
    squiffy.story.go("nutrition facts");

If the brief was just "split a string into words and count how many times each appears", I would go for something more like:

    let food = "For breakfast, I had leftover chicken. For lunch, I had more leftover chicken.";
    var matched = food.match(/\w+/g).reduce((matched, word) => ++matched[word] && matched, {});
    $.each(matched, (word, number) => squiffy.set (word, number));

Hopefully those are all simple enough to understand. Not sure how many of the core javascript and/or jQuery functions you're familiar with. If you'd like an explanation of any of it, let me know :)


I'm awed and impressed as always, mrangel. The mess in my op is about the extent of my familiarity with js. I'm just monkeying with it like I did when I learned Excel or Squiffy. I like to see what works and how before trying to learn the next piece . I did try a sentence with 'a', and sure enough, it counted all the letter a's.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums