This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Loop through variables
#1
Hi

Is it possible to loop through a set of variables, or maybe determine variable name depending on other values?

I have a project where I need to count the presence for each ventilation system for each floor to be able to calculate the percentage of offices that are in use. For this I need two variables for each system for each floor; one for the number of occupied offices and one for the total number of offices.

In the name and address of the objects I can find both the floor and the ventilation system, so what I want to do is to scan through all the occupied-addresses and add values to the different variables depending on the value of the addresses.

I more or less has it working, but there is a lot of if/elseif and so on to be able to check it all. So I was thinking there must be a more elegant way to do it.

The code is not done yet, I still need to transfer values to group addresses, but this is what I have so far:

 
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"') calcWeight = false --Bestemmer om vekt skal medregnes i totalt antall OCCUPIED-adresser. Med false vil hver adresse kun telle som 1. local p1_03_04count = 0 local p1_03_04occ = 0 local p2_03_04count = 0 local p2_03_04occ = 0 local p3_03_04count = 0 local p3_03_04occ = 0 local p4_03_04count = 0 local p4_03_04occ = 0 local p5_03_04count = 0 local p5_03_04occ = 0 local p1_05count = 0 local p1_05occ = 0 local p2_05count = 0 local p2_05occ = 0 local p3_05count = 0 local p3_05occ = 0 local p4_05count = 0 local p4_05occ = 0 local p5_05count = 0 local p5_05occ = 0 local p1_02count = 0 local p1_02occ = 0 local p2_02count = 0 local p2_02occ = 0 local p3_02count = 0 local p3_02occ = 0 local p4_02count = 0 local p4_02occ = 0 for _, name in ipairs(obj) do   adr = grp.find(name.name)   gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')   weight = grp.getvalue(gaWeight)   value = toboolean(grp.getvalue(name.name))   if value then value = 1 else value = 0 end   etasje = string.split(adr.address, '/')[2]   agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]     --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.   if grp.find(gaWeight) == nil then     address = grp.create({         datatype = dt.uint16,         virtual = true,         name = gaWeight,         comment = '',       })     grp.write(gaWeight, 1)   end   --log(value, etasje, agg, weight)     if etasje == '1' then     if agg == '02' then       log(name.name, value, etasje, agg, weight)       p1_02count = p1_02count + 1       p1_02occ = p1_02occ + (value * weight)     elseif agg == '03_04' then       p1_03_04count = p1_03_04count + 1       p1_03_04occ = p1_03_04occ + (value * weight)     elseif agg == '05' then       p1_05count = p1_05count + 1       p1_05occ = p1_05occ + (value * weight)     end   elseif etasje == '2' then     if agg == '02' then       --log(name.name, value, etasje, agg, weight)       p2_02count = p2_02count + 1       p2_02occ = p2_02occ + (value * weight)     elseif agg == '03_04' then       p2_03_04count = p2_03_04count + 1       p2_03_04occ = p2_03_04occ + (value * weight)     elseif agg == '05' then       p2_05count = p2_05count + 1       p2_05occ = p2_05occ + (value * weight)     end   elseif etasje == '3' then     if agg == '02' then       --log(name.name, value, etasje, agg, weight)       p3_02count = p3_02count + 1       p3_02occ = p3_02occ + (value * weight)     elseif agg == '03_04' then       p3_03_04count = p3_03_04count + 1       p3_03_04occ = p3_03_04occ + (value * weight)     elseif agg == '05' then       p3_05count = p3_05count + 1       p3_05occ = p3_05occ + (value * weight)     end   elseif etasje == '4' then     if agg == '02' then       --log(name.name, value, etasje, agg, weight)       p4_02count = p4_02count + 1       p4_02occ = p4_02occ + (value * weight)     elseif agg == '03_04' then       p4_03_04count = p4_03_04count + 1       p4_03_04occ = p4_03_04occ + (value * weight)     elseif agg == '05' then       p4_05count = p4_05count + 1       p4_05occ = p4_05occ + (value * weight)     end   elseif etasje == '5' then     if agg == '02' then       --log(name.name, value, etasje, agg, weight)       p5_02count = p5_02count + 1       p5_02occ = p5_02occ + (value * weight)     elseif agg == '03_04' then       p5_03_04count = p5_03_04count + 1       p5_03_04occ = p5_03_04occ + (value * weight)     elseif agg == '05' then       p5_05count = p5_05count + 1       p5_05occ = p5_05occ + (value * weight)     end   end             --log(adr.name, etasje, agg) end log(p1_02count, p1_02occ)
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply
#2
Use arrays/tables to store data like this. Untested modified version of you code:
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"') data = {} keys = { '02', '03_04', '05' } for fid = 1, 5 do   floor = {}   for _, key in ipairs(keys) do     floor[key] = {       count = 0,       occ = 0,     }   end   data[fid] = floor end for _, name in ipairs(obj) do   adr = grp.find(name.name)   gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')   weight = grp.getvalue(gaWeight)   value = toboolean(grp.getvalue(name.name))   floor = tonumber(string.split(adr.address, '/')[2])   agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]      --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.   if grp.find(gaWeight) == nil then     address = grp.create({         datatype = dt.uint16,         virtual = true,         name = gaWeight,         comment = '',       })     grp.write(gaWeight, 1)     weight = 1   end   if data[floor] and data[floor][agg] then     data[floor][agg].count = data[floor][agg].count + 1     if value then       data[floor][agg].occ = data[floor][agg].occ + weight     end   end end log(data)
Reply
#3
(11.02.2021, 14:28)admin Wrote: Use arrays/tables to store data like this. Untested modified version of you code:
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"') data = {} keys = { '02', '03_04', '05' } for fid = 1, 5 do   floor = {}   for _, key in ipairs(keys) do     floor[key] = {       count = 0,       occ = 0,     }   end   data[fid] = floor end for _, name in ipairs(obj) do   adr = grp.find(name.name)   gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')   weight = grp.getvalue(gaWeight)   value = toboolean(grp.getvalue(name.name))   floor = tonumber(string.split(adr.address, '/')[2])   agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]     --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.   if grp.find(gaWeight) == nil then     address = grp.create({         datatype = dt.uint16,         virtual = true,         name = gaWeight,         comment = '',       })     grp.write(gaWeight, 1)     weight = 1   end   if data[floor] and data[floor][agg] then     data[floor][agg].count = data[floor][agg].count + 1     if value then       data[floor][agg].occ = data[floor][agg].occ + weight     end   end end log(data)

Great! 

I will test this out. It looks a lot more elegant than my solution. I believe I will be needing things like this in many other applications as well.
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply
#4
OK, so I got this finnished and tested. It works very well. I added some extra info to the table to get more data available, other than that I kept most of the code from Admin.

Thanks for the great help in learing to code in this forum! It is always productive and on-the-spot help here!

I wont bother to post the final code as it is very project spesific, and probably not of interest to anyone else.
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply


Forum Jump: