Iterating over a string... in a wacky way.

Posted by Worstje on Tue 22 Apr 2008 05:33 AM — 5 posts, 22,920 views.

Netherlands #0
Hello all,

Let's get to the point right away. =) Right now I am looping through a string with `for word in str:gmatch("%w+") do`.

Is there any way in which I can write a subloop that will take `word` and all that remains, and then continues to take words away?

For example, I have the string 'a b c'. Now I process 'a' in my outer-loop, and inner-loop should go ['a b c', 'a b', 'a']. Next 'b' goes ['b c', 'b']. Last comes 'c', which goes ['c'].

I can personally only think of an ugly way to do this with two while loops, but I have the feeling it could be done in a neater fashion. Is there anyone here willing to point me in the right direction?
USA #1
Is this an accurate restatement:


Let w be the first word of the string s.
Let s2 be a copy of s.
While there are words in s2:
  Remove the last word from s2.
Remove w from s.
If s is empty, end; else, go to beginning.


I ask because your outer loop seems to go forward whereas your inner loop goes backward. Your English explanation didn't quite correspond to that, so I wanted to make sure I knew exactly what you're trying to do.
Australia Forum Administrator #2
Try this thread:

http://www.gammon.com.au/forum/bbshowpost.php?id=6544

Amongst other things there is a "general splitting iterator" which is pretty much what you are trying to do. Rather than split at newlines, you want to split at spaces. However if you really need the "first word" and "rest of line" you may need to modify it a bit.
Netherlands #3
Heh, it seems I have bothered all of you for nothing. You'll always see you think about a problem for a few hours and can't figure it out, then you ask for help and the next time you think of the issue, you solve it almost naturally.


local words = {}
local skipTillWord = 0
for word in description:gmatch("%w+") do words[#words+1] = word end
for i=1,#words do
	if (i > skipTillWord) then
		
		for j=#words,i,-1 do
			local substring = table.concat(words, " ", i, j)
			
			if (WordCombinations[substring] ~= nil) then
				-- Bingo. Process it in whatever way I want to.
				
				-- Make sure not to recognise sub-word-combinations part of this one.
				skipTillWord = j
				break
			end
		end
	end
end


It is indeed so that the outer loop counts up, whereas the inner loop counts down. I need to match the biggest possible word combinations and not match the smaller versions if it can be helped. (Suppose WordCombinations has both keys "a b", "a" and "b", it should track the "a b" where possible and not the lonely "a" nor lonely "b"). There's still a minor case of overlapping that isn't handled (inputting "a b c" while WordCombinations contains "a b" and "b c" will only result the "a b" match and never the secondary one), but for my code that isn't of any importance.

I hope this makes clear what I was trying to achieve. =)
Australia #4
follow me guy.

the way is to dynamicly generate the reg expression.

eg:
word combination: "a b c", you can generate some reg expresses in a particular order you wanna do the checking.
then put them in a table like {"a b", "b c"}. finally do a loop to reg.new(tables[i]):exec("a b c").

thatz all.