L
L
Leatington2021-10-20 15:10:23
Lua
Leatington, 2021-10-20 15:10:23

Metatables and the __newindex method - how to merge two-dimensional arrays?

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
})


My question is: when adding a new line to the table, the number should increase by 1, because the standard operator "#" will not work here. My question is, is it possible to somehow simplify my code by making one out of two setmetatable?
Lua version: 5.1, so redeclaring the statement will not work

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vadim Ushakov, 2021-11-06
@Leatington

What is the meaning of the code? Can you be more specific about what needs to be done? What does the union of two one-dimensional arrays mean? With __newindex ... you count the number of new fields when you create them in the 'control' and 'data' tables.

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)

--

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


-- 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[<название-ключа-таблицы>]


Didn't test.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question