many to many mapping in Grails - grails

devices :[1.1:Acer C6, 2:Acer C6, 1:Acer C6, 2.2:HTC Magic]
files :[2:Tetris.apk, 1:TheSims3.apk]
I have a mapping of files and devies, as of now its one-to-many mapping.
devices :[1.1:Acer C6, 2:Acer C6, 1:Acer C6, 2.2:HTC Magic]
files :[2:Tetris.apk, 1:TheSims3.apk]
Now I need to implement many-to-many mapping
my logic for one-to-many mapping is
mapping = params.devices.inject( [:] ) { map, dev ->
// Get the first part of the version (up to the first dot)
def v = dev.key.split( /\./ )[ 0 ]
logger.debug("value of v :"+v)
map << [ (dev.value): files[ v ] ]
}
current output is - mapping :[Acer C6:Tetris.apk, HTC Magic:Tetris.apk]
expected output : [Acer C6:Tetris.apk, Acer C6:TheSims3.apk, HTC Magic:Tetris.apk]

You are accumulating your results using the device name as a key. When a new value is added to the map, it overwrites the last one with the same key.
You could try accumulating into a Set instead of a map. Example:
def devices = ['1.1': 'Acer C6', '2': 'Acer C6', '1': 'Acer C6', '2.2': 'HTC Magic']
def files = ['2': 'Tetris.apk', '1': 'TheSims3.apk']
def deviceFiles = devices.inject([] as Set) { deviceFiles, device ->
def v = device.key.split( /\./ )[0]
deviceFiles << [ (device.value), files[ v ] ]
}
assert deviceFiles == [
['Acer C6', 'Tetris.apk'],
['Acer C6', 'TheSims3.apk'],
['HTC Magic', 'Tetris.apk']
] as Set

Related

How to create links in netlogo from ArcGIS shapefile

I have successfully loaded other ArcGIS shapefiles e.g., river polygon.However I am trying to draw/ create links by loading a polyline shapefile. Here is an extract of the code.
set river_area gis:load-dataset "River_data/April_28_2018_800m_Lines.shp"
set river_zones gis:load-dataset "River_data/May 5 2018_River_polygon_Zones.shp"
set polylines_links gis:load-dataset "River_data/Milford_Possible_routes_Polylines.shp"
Below is the code (from another source)for creating links and nodes. How can I modify it to work on the code that I am developing ?
foreach polylines-of polylines_links node-precision [
(foreach butlast ? butfirst ? [ if ?1 != ?2 [
let n1 new-node-at first ?1 last ?1
let n2 new-node-at first ?2 last ?2
ask n1 [create-link-with n2]
]])
]
I guess this is what you are looking for. Happy coding!
foreach polylines-of polylines_links node-precision [
x ->
(foreach butlast x butfirst x [
[a b] -> if a != b
[
let n1 new-node-at first a last a
let n2 new-node-at first b last b
ask n1 [create-link-with n2]
]
])
]

How to save a value of a table into a variable using Lua?

I'm trying to improve my home automation with the Fibaro HC2.
The building is divided into several sections and I want to create a list of devices with the name of the section. With the Fibaro API I only get the Section ID, but not the name. With json.encode I get the contents of this table:
[
{
"Id":4,
"sortOrder":3,
"name":"basement"
},
{
"id":5,
"sortOrder":2,
"name":"GROUND FLOOR"
},
{
"id":6,
"sortOrder":4,
"name":"FIRST FLOOR"
},
{
"id":7,
"sortOrder":1,
"name":"OUTSIDE"
}
]
sortOrder does not matter. What I have done:
local jS = json.encode (sections)
for i = 1, #sections do
local jS = json.encode (sections [i])
s = string.gsub (jS, ', "sortOrder":% d', "")
print (s)
end
This is the output:
{ "Id": 4, "name": "BASEMENT"}
{ "Id": 5, "name": "GROUND FLOOR"}
{ "Id": 6, "name": "FIRST FLOOR"}
{ "Id": 7, "name": "OUTSIDE"}
I have no idea if that makes sense. I would like to have a function that stores the name in a variable:
function getSectionNamebyID (secID)
if secId == "4" then sectionname = "BASEMENT" end
if secId == "5" then sectionname = "GROUNDFLOOR" end
--...
return sectionname
end
A very nice tutorial on how to read all devices etc. in fibaro and store that table of information as a json string value in a global variable.
The most interesting part is the script which is implemented as a lua scene in fibaro. Just create a global variable with the name "HomeTable" and run the scene manually to store all devices/scenes etc. in one variable:
--[[
%% autostart
%% properties
%% events
%% globals
--]]
local debug = true --set to false to stop debug messages
-- HOME TABLE FOR ANYTHING IN ADDITION TO DEVICES, VDs, iOS DEVICES
-- EDIT TO YOUR NEEDS OR KEEP BLANK: jsonHome = {}
jsonHome = {
scene = {
HueSceneStart=43,
AlexaSceneStart=67,
},
users = {
--admin=2,frank=1564,sylvia=1565
},
}
-- NO USER EDITS NEEDED BELOW
local function log(str) if debug then fibaro:debug(str); end; end
devices=fibaro:getDevicesId({visible = true, enabled = true}) -- get list of all visible and enabled devices
log("Fill hometable with "..#devices.." devices")
-- FILL THE HOMETABLE WITH ALL VDs, DEVICES AND iOS DEVICES
for k,i in ipairs(devices) do
deviceName=string.gsub(fibaro:getName(i), "%s+", "") -- eliminate spaces in devicename
-- Uncomment this to eliminate all non-alphanumeric characters in devicename
-- deviceName=string.gsub(fibaro:getName(i), "%W", "")
if fibaro:getType(i) == "virtual_device" then -- Add VDs to Hometable
if jsonHome.VD == nil then -- Add VD to the table
jsonHome.VD = {}
end
jsonHome.VD[deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
elseif fibaro:getType(i) == "iOS_device" then -- Add iOS devices to Hometable
if jsonHome.devices == nil then -- Add iOS devices to the table
jsonHome.devices = {}
end
jsonHome.devices[deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
else -- Add all other devices to the table
roomID = fibaro:getRoomID(i)
if roomID == 0 then
roomname = "Unallocated"
else
roomname=string.gsub(fibaro:getRoomName(roomID), "%s+", "") -- eliminate spaces in roomname
-- Uncomment this to eliminate all non-alphanumeric characters in roomname
-- roomname=string.gsub(fibaro:getRoomName(roomID), "%W", "")
end
if jsonHome[roomname] == nil then -- Add room to the table
jsonHome[roomname] = {}
end
jsonHome[roomname][deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName..", room="..roomname)
end
end
jHomeTable = json.encode(jsonHome) -- ENCODES THE DATA IN JSON FORMAT BEFORE STORING
fibaro:setGlobal("HomeTable", jHomeTable) -- THIS STORES THE DATA IN THE VARIABLE
log("global jTable created:") -- STANDARD DEBUG LINE TO DISPLAY A MESSAGE
log(jHomeTable)
After running it, you can use it by following example. In my case the room name was "Workingroom" and the name of the device was "Shutter":
--[[
%% properties
%% events
%% globals
--]]
local ht = json.decode(fibaro:getGlobalValue("HomeTable"))
fibaro:call(ht.Workingroom.Shutter, "open")

Combine two Groovy maps and get differences [duplicate]

This question already has an answer here:
Compare two maps and find differences using Groovy or Java
(1 answer)
Closed 6 years ago.
I have two maps and I would like to combine this maps into new map with the differences. I mean with differences is if startDate or appId are different for that cuInfo and service.
Notice: The attributes cuInfo and service are unique in both maps.
Map 1:
[
[name:"Apple",cuInfo:"T12",service:"3",startDate:"14-02-16 10:00",appId:"G12351"],
[name:"Apple",cuInfo:"T13",service:"3",startDate:"14-01-16 13:00",appId:"G12352"],
[name:"Apple",cuInfo:"T16",service:"3",startDate:"14-01-16 13:00",appId:"G12353"],
[name:"Google",cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12301"],
[name:"Microsoft",cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]
]
Map 2:
[
[cuInfo:"T12",service:"3",startDate:"14-01-16 13:22",appId:"G12355"],
[cuInfo:"T13",service:"3",startDate:"12-02-16 13:00",appId:"G12356"],
[cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12300"],
[cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]
]
I would like to get map below as final result:
[
[name:"Apple",cuInfo:"T12",service:"3",startDate:"14-02-16 10:00",appId:"G12351",startDate2:"14-01-16 13:22",appId2:"G12355"],
[name:"Apple",cuInfo:"T13",service:"3",startDate:"14-01-16 13:00",appId:"G12352",startDate2:"12-02-16 13:00",appId2:"G12356"],
[name:"Google",cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12301",startDate2:"10-01-16 11:20",appId2:"G12300"]
]
I tried the code below but it gives not what I want:
def total = [list1: list1, list2: list2].collectEntries { label, maps ->
[(label): maps.countBy { it.iccId} ]
}.inject([:]) { result, label, counts ->
counts.entrySet().each { entry ->
if(!result[entry.key]) result[entry.key] = [:]
result[entry.key][(label)] = entry.value
}
result
}.collect { iccId , counts -> [iccId: iccId] << counts }
The code above give me this, it merge the maps and count the cuInfos but I'm not able to get the differences:
[
[cuInfo:T12, list1:1, list2:1], [cuInfo:T13, list1:1, list2:1], [cuInfo:T14, list1:1, list2:1], [cuInfo:T15, list1:1, list2:1],[cuInfo:T16, list1:1]
]
Please who can help to get it work please with example. Thanks
Is that what you're looking for:
def col1 = [
[name:"Apple",cuInfo:"T12",service:"3",startDate:"14-02-16 10:00",appId:"G12351"],
[name:"Apple",cuInfo:"T13",service:"3",startDate:"14-01-16 13:00",appId:"G12352"],
[name:"Apple",cuInfo:"T16",service:"3",startDate:"14-01-16 13:00",appId:"G12353"],
[name:"Google",cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12301"],
[name:"Microsoft",cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]
]
def col2 = [
[cuInfo:"T12",service:"3",startDate:"14-01-16 13:22",appId:"G12355"],
[cuInfo:"T13",service:"3",startDate:"12-02-16 13:00",appId:"G12356"],
[cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12300"],
[cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]
]
col1
.findAll { it.cuInfo in col2.cuInfo && !(it.subMap('cuInfo', 'service', 'startDate', 'appId') in col2) }
.collect {
def e = col2.find { i2 -> it.cuInfo == i2.cuInfo }
it << [startDate2: e.startDate, appId2: e.appId]
}
.each {
println it
}
?

Lua: set of k-dimensional points

I want to make sure that kD points which I generate randomly don't happen to be identical. To test this efficiently, I want to use a set (at least that's what I would do in C++).
I know that in Lua tables can be used as sets by inserting the object as value with any non-nil key (typically just true or an integer for multisets).
But the problem is that tables in Lua are by default just compared w.r.t. their address, which is of course different even if all the vector components (in my case) are equal.
So I thought I'd implement a equal and/or less than metamethod for my points. But this didn't work (see code below). Can anybody help?
local k = 3
local mt = {}
mt.__eq = function( a, b )
for dim = 1, k do
if a[dim] ~= b[dim] then return false end
end
return true
end
mt.__lt = function( a, b )
for dim = 1, k do
if a[dim] < b[dim] then
return true
elseif a[dim] > b[dim] then
return false
end
end
return false -- equal
end
local set = {}
local p1 = { 1, 2, 3 }
setmetatable( p1, mt )
set[p1] = true
local p2 = { 1, 2, 3 }
setmetatable( p2, mt )
set[p2] = true -- should just overwrite the old value
print( "p1 == p2 --> "..tostring( p1 == p2 ) )
print( "p1 < p2 --> "..tostring( p1 < p2 ) )
local setSize = 0
for _, _ in pairs( set ) do
setSize = setSize + 1
end
print( "Size of the set: "..setSize )
Lua has no facilities for allowing what you're trying to do. That is, there's no metamethod trickery that can make two different pieces of userdata or two different tables map to the same index to the table indexing system.
You'll have to do this manually. You can effectively write your own set, by keeping a list of vectors sorted. table.sort can do the job, since you already have an appropriate __lt metamethod.
If anyone is interested: I have come up with another work-around that has worked for me.
One can use a set of x-coordinates and instead of associating the set items with just "true" or "1", the respective values are sets themselves (of y-coordinates); and so on.
This leads to a tree-like structure where the path to each leaf represents a point (sequence of coordinates) and points with the same first coordinates have common parent nodes. Also all points are unique.

converting set to a map groovy

I have my logic in my postprocess to process the values of devices and files as below :(changed this to set from map as it was overriding the values)
def deviceFiles = devices.inject([] as Set) { deviceFiles, device ->
def v = device.key.split( /\./ )[0]
deviceFiles << [ (device.value), files[ v ] ]
}
output : deviceFiles :[[Acer C6, Tetris.apk], [Motorola Droid Milestone, Tetris.apk], [Acer C6, TheSims3.apk], [HTC Desire, TheSims3.apk]] --- looks good to be displayed
These values are to be passed as a map/properties so that the data would be displayed properly without any cast exceptions, which I am finding tough..
when it is looped through the set
deviceFiles.each { device ->
mapping.put("${device}", "${file}")
}
output : mapping :[HTC Desire:TheSims3.apk, Motorola Droid Milestone:Tetris.apk, Acer C6:Tetris.apk] -- which is not correct (Acer C6:TheSims3.apk has been overriden)
Am I missing something here in sending the expected values into map? or it is not possible to send the values of set through map(as map always eliminates the duplicates when i am iterating through devices) ???
You could use collectEntries:
def deviceFiles = devices.collectEntries {
device -> [device.value, device.key.split(/\./)[0]]
}
You can use groupBy for this. Assuming your set consists of:
def deviceFiles = [["Acer", "test.apk"], ["Acer", "abc.apk"], ["HTC", "qwer.apk"]]
def mapping = deviceFiles.groupBy { it[0] }
Will result in:
["Acer": [["Acer", "test.apk"], ["Acer", "abc.apk"]], "HTC": [["HTC", "qwer.apk"]]]

Resources