Я люблю Lua. I love Lua.

Регулярные выражения

Posted in Uncategorized by ilovelua on Декабрь 19, 2011

Задача: есть таблица table. Ключ для записи задается в виде «field1.field2.field3.field4.field5.field». Нужно в этой таблице записать значение:

table[field1][field2][field3][field4][field5][field] = value

Некоторые поля в таблице, что характерно, могут отсутствовать.

Решение:

function setTableValue(table, key, value)
  local currField = table

  for currKey, separator in string.gmatch(key, "(%w+)(.?)") do
    if '' == separator then
      currField[currKey] = value
    else
      if not currField[currKey] then
        currField[currKey] = {}
      end

      currField = currField[currKey]
    end
  end
end

Проверим:

print('***test***')
local t = {}
setTableValue(t, "number", 1)
print('t.number', t.number)
setTableValue(t, "theme.color", 2)
print('t.theme.color', t.theme.color)
setTableValue(t, "theme.border.color.1", 3)
print('t.theme.border.color[1]', t.theme.border.color[1])

***test***
t.number 1
t.theme.color 2
t.theme.border.color[1] nil

Упс! Немного не то, что мы ожидали увидеть.

Если поменять код проверки на:

print('t.theme.border.color[1]', t.theme.border.color['1'])

То вывод будет ожидаемым:

t.theme.border.color[1] 3

Значит, нам нужно как-то различать цифровые и строковые ключи. Переделаем формат ключа на:

field1.field2.field3.field4.field5.[field]

где квадратные скобки вокруг ключа будут означать необходимость привести ключ к числовому типу.

function setTableValue(table, key, value)
  local currField = table

  for currKey, separator in string.gmatch(key, "([^\.]+)(.?)") do
    local numericKey = string.match(currKey, "%[(.*)%]")

    if numericKey then
      currKey = tonumber(numericKey)
    end

    if '' == separator then
      currField[currKey] = value
    else
      if not currField[currKey] then
        currField[currKey] = {}
      end

      currField = currField[currKey]
    end
  end
end

Проверим:

print('***test***')
local t = {}
setTableValue(t, "number", 1)
print('t.number', t.number)
setTableValue(t, "theme.color", 2)
print('t.theme.color', t.theme.color)
setTableValue(t, "theme.border.color.[1]", 3)
print('t.theme.border.color[1]', t.theme.border.color[1])
setTableValue(t, "theme.border.[4].color.[1]", 5)
print('t.theme.border.[4].color.[1]', t.theme.border[4].color[1])

Результат:
***test***
t.number 1
t.theme.color 2
t.theme.border.color[1] 3
t.theme.border.[4].color.[1] 5

Работает!

Реклама

комментария 4

Subscribe to comments with RSS.

  1. Valery said, on Декабрь 20, 2011 at 11:26 дп

    А на кой » в t.»theme?

    • ilovelua said, on Декабрь 20, 2011 at 11:32 дп

      Э… Условие такое, типа…
      Я не создаю таблицу theme, а в существующую таблицу t добавляю поле theme.

      • Valery said, on Декабрь 23, 2011 at 2:31 пп

        Ты не понял. Посмотри внимательно на последний вызов print при проверке — там лишние двойные кавычки внутри строки перед theme.

      • ilovelua said, on Декабрь 26, 2011 at 4:54 дп

        Исправлено! 🙂


Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: