4

Normally I use two variables to store the output of something like this:

a = {'alarm boy car dentist','alarm car dentist elephant','alarm dentist elephant fabulous','alarm elephant fabulous goat'}
k, v = string.match(a[1], 'alarm dentist (%w+) (%w+)' )
print(k, v)
elephant fabulous

but instead of using two variables I would like to store it in an array or table.

My final goal is to create a function where I input an array (which in this case is 'a') and a pattern (which is this case is 'alarm dentist (%w+) (%w+)') and that it returns the desired accompanying word/s if found or 'nil' otherwise. The catch is that the number of word that the pattern looks for is undefined. In this case is 2 but I want the user to be able to input any pattern, i.e. 'alarm dentist (%w+) (%w+) (%w+) (%w+)' or 'alarm dentist (%w+)'.

So this was my line of thought so far: (I'm using the command line tool in Ubuntu 12.04LTS to test it)

a = {'alarm boy car dentist','alarm car dentist elephant','alarm dentist elephant fabulous','alarm elephant fabulous goat'}
function parse_strings (array, pattern)
words = nil
for i=1, #array do
    c = string.match(array[i], pattern)
    if c ~= nil then
        words = c
        end
    end
    return words
end
print (parse_strings (a, 'alarm dentist (%w+) (%w+)'))
elephant

but only the first value is stored in "c" instead of c[1]='elephant' and c[2]='fabulous'.

Worst case I could search for how many words the pattern is searching for but I would still need to find a way to store the undefined size output from string.match in one array.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
user3325563
  • 187
  • 2
  • 12

2 Answers2

5

You can store the result into a table:

local t = {string.match(array[i], pattern)}
if #t ~= 0 then
    words = t
    end
end

The return value of parse_string is a table now:

local result =  (parse_strings (a, 'alarm dentist (%w+) (%w+)'))
for k, v in ipairs(result) do
    print(k, v)
end
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Why not use `{ string.match(whatever) }` instead of `table.pack(string.match(whatever))` ? – Niccolo M. May 22 '14 at 06:44
  • @NiccoloM. You are right, I was overthinking. I've modified it to use a table constructor. Thanks. – Yu Hao May 22 '14 at 06:53
  • Sorry to ask this here, but this is my first question, do I have to do something else in addition to accept your answer? – user3325563 May 22 '14 at 15:52
  • @user3325563 Now that you have over 15 reputation, you can also upvote the answers that help you if you want. You don't *have to* do anything. – Yu Hao May 23 '14 at 00:35
0

Since there are two captures in your pattern, you need two result variables for match. Try:

words = nil
for i=1, #array do
    c,d = string.match(array[i], pattern)
    if c ~= nil then
        words = {c,d}
        return words
    end
end

This gives...

> for k,v in ipairs(words) do print (k,v) end
1   elephant
2   fabulous
Doug Currie
  • 40,708
  • 1
  • 95
  • 119
  • Thanks, Doug. Yes, this is how I normally do it, but the issue here is the undefined number of words to search (it can be 1,2,3,...), but the solution above addresses this. – user3325563 May 22 '14 at 15:50