@Leatington

Метатаблицы и метод __newindex — как объеденить двумерные массивы?

local clients = {
  ['control'] = {},
  ['count'] = {0, 0},
  ['data'] = {},
}

setmetatable(clients['control'], {
  __newindex = function(self, key, value)
    clients['count'][2] = (clients['count'][2] + 1)
    rawset(self, key, value)
  end
})
setmetatable(clients['data'], {
  __newindex = function(self, key, value)
    clients['count'][1] = (clients['count'][1] + 1)
    rawset(self, key, value)
  end
})


У меня такой вопрос: при добавлении новой строчки в таблицу число должно увеличиваться на 1, ибо стандартный оператор "#" тут не прокатит. У меня вопрос, возможно ли как то упростить мой код, сделав из двух setmetatable одну?
Версия Lua: 5.1, поэтому переобъявить оператор не получится
  • Вопрос задан
  • 47 просмотров
Решения вопроса 1
Nightmare1
@Nightmare1
Программист
В чём смысл кода ? Есть возможность конкретнее описать что требуется сделать ? Что значит объединение двух одномерных массивов ? При __newindex ... у тебя считается кол-во новых полей при создании в таблицах 'control' и 'data' .

local clients = {
  ['count'] = {0, 0},
  ['control'] = {},
  ['data'] = {},
}

local function set_counter_for_new_indexes_to(t, id)
	setmetatable(t, {
		__newindex = function(self, key, value)
			clients['count'][id] = clients['count'][id] + clients['count'][id]
			rawset(t, key, value)
		end
	})
end
set_counter_for_new_indexes_to(clients['control'], 2)
set_counter_for_new_indexes_to(clients['count'], 1)

--[[
	variant #2
]]

local clients =
{
  	['control'] = {},
  	['data'] = {},
}

--
-- автоматически добавляет параметр .count к таблице в которой создается новой поле
--
local function set_counter_for_new_indexes_to(t)
	setmetatable(t, {
		__newindex = function(self, key, value)
			if not rawget(self, 'count') then rawset(self, 'count', 1)
			else
				rawset(self, 'count', rawget(self, 'count'))
			end
			rawset(t, key, value)
		end
	})
end

-- применяет счётчик полей к кождой подтаблице в таблице clients
for k, v in pairs(clients) do
	if type(v) == "table" then continue end
	set_counter_for_new_indexes_to(v)
end


--[[ VARIANT_#3 ]] local clients =
{
  	['control'] = {},
  	['data'] = {},
}


local function initialize_fields_counter(t)
	if not t.table_fields_counters then
	t.table_fields_counters = {} end
	local ni_method = {__newindex = function(self, key, value)
		local kname = t.table_fields_counters[self]
		t.table_fields_counters[kname] = 
			(t.table_fields_counters[kname] or 0) + 1

		rawset(t, key, value)
	end}

	for k, v in pairs (t) do
		if type(v) == "table" then continue end
		t.table_fields_counters[v] = k
		setmetatable( v, ni_method )
	end
end initialize_fields_counter(clients )

-- получить счётчик элементов .

clients.t.table_fields_counters[<название-ключа-таблицы>]


Не тестировал.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы