Convert map to yaml file - jenkins

I'm trying to create yaml file from a map with yamlBuilder but it's not in the right context that I need it to be.
For example:
Map mymap = [1: "a, b, c ,d", 2: "y, d, x"]
The yamlfile that I want to look like:
-Content:
-1:
-a
-b
-c
-d
-2:
-y
-d
-x
How the syntax of creation the yaml file should be?
I've tried:
def yamlFile = new YamlBuilder()
yamlFile{
myMap
}
but this is not the same design as I need it to be.
Thanks

Ok, so with the map you dropped in the question, you can do:
import groovy.yaml.YamlBuilder
Map mymap = [1: "a, b, c ,d", 2: "y, d, x"]
def config = new YamlBuilder()
config {
"Content" mymap
}
println config.toString()
Which prints
---
Content:
"1": "a, b, c ,d"
"2": "y, d, x"
As you can see, your input map just has String values, not lists...
If you meant to give your input map as:
Map mymap = [1: ["a", "b", "c", "d"], 2: ["y", "d", "x"]]
Then the above code prints out
---
Content:
"1":
- "a"
- "b"
- "c"
- "d"
"2":
- "y"
- "d"
- "x"
Which is what you say you want...
If the original map was correct and you're being sent comma separated Strings to represent lists, then you'll need to munge them yourself into lists
Map mymap = [1: "a, b, c ,d", 2: "y, d, x"]
mymap = mymap.collectEntries { k, v ->
[k, v.split(",")*.trim()]
}
def config = new YamlBuilder()
config {
"Content" mymap
}
println config.toString()
Which again gives you
---
Content:
"1":
- "a"
- "b"
- "c"
- "d"
"2":
- "y"
- "d"
- "x"

Related

How to prevent changes to copied variables?

I have two variables, A and B with Map data type, when A is copied with B then I make changes in A, but B also changes. The expected result only A changed, how to solve it? Thank you
List a = [{"id": 1, "data": []}], b = [];
void main() {
b = List.from(a);
a[0]['data'].add(123);
// result
print(a); // [{id: 1, data: [123]}]
print(b); // [{id: 1, data: [123]}]
// expected results
// print(a); // [{id: 1, data: [123]}]
// print(b); // [{id: 1, data: []}]
}
you can use dart:convert
b = json.decode(json.encode(a));
or
b = [...a.map((e) => {...e})];
In my case its working fine you can check in the screenshot attached. I created a simple array.
var arr = ['a','b','c','d','e'], b=[];
void main() {
b = List.from(arr);
arr[0] = "100";
for (int i = 0; i < arr.length; i++) {
print('hello ${arr[i]}');
print('hello ${b[i]}');
}
}
Output -
hello 100
hello a
hello b
hello b
hello c
hello c
hello d
hello d
hello e
hello e

Deserialization of simple Lua table stored as string

I'm transfering a lua table literal in a string from a web application in to PICO-8 that I'm trying to deserialize back in to a lua table in PICO-8.
The string is in the form '{"top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}'
To try and keep things simple I'm only going to include lowercase characters in the strings and only strings are allowed in the nested tables.
I feel like I've got a grasp on parsing the characters, but I don't know how to keep track of where I am in the recreated data, both the depth of the structure and the index.
How is this usually done?
The catch is that as PICO-8 lua doesn't contain load or loadstring the parsing has to be done manually. The following code is using table.insert and string.sub instead of the PICO-8 equivalents because I'm using a lua REPL to help prototype this code.
Here is what I have so far with print statements what I think I need to do where.
Any help would be greatly appreciated.
test_obj = {"top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}
data_string = '{"top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}'
data = nil
string = ''
level = 0
while #data_string > 0 do
local d=string.sub(data_string,1,1)
if stringChar(d) then
string = string..d
end
if comma(d) then
print(string)
table.insert(data, string)
string = ''
end
if openBracket(d) then
if data == nil then
data = {}
print('new table')
else
print('insert table')
end
level = level + 1
print('on level', level)
end
if closeBracket(d) then
print('end of table')
level = level - 1
print('up to level', level)
end
data_string=string.sub(data_string,2)
end
Use Lua patterns to avoid parsing each character
local function read_exp_list(s)
local exps, res = {}, {}
local function save(v)
exps[#exps + 1] = v
return ('\0'):rep(#exps)
end
s = s:gsub('%b{}', function(s) return save{read_exp_list(s:sub(2, -2))} end) -- arrays
s = s:gsub('"(.-)"', save) -- strings
s = s:gsub('%-?%d+', function(s) return save(tonumber(s)) end) -- integer numbers
for k in s:gmatch'%z+' do
res[#res + 1] = exps[#k]
end
return (table.unpack or unpack)(res)
end
local data_string = '{-42, "top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}'
local obj = read_exp_list(data_string)
-- obj == {-42, "top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}
Strings must be enclosed in " and must not contain characters {}\ inside. String may be empty.
Numbers must be integer in decimal notation with optional minus.
Arrays must contain only strings, numbers and subarrays. Array may be empty.
UPDATE:
The following code only uses functions string.sub, table.insert, tonumber, type
local function is_digit(c)
return c >= '0' and c <= '9'
end
local function read_from_string(input)
if type(input) == 'string' then
local data = input
local pos = 0
function input(undo)
if undo then
pos = pos - 1
else
pos = pos + 1
return string.sub(data, pos, pos)
end
end
end
local c
repeat
c = input()
until c ~= ' ' and c ~= ','
if c == '"' then
local s = ''
repeat
c = input()
if c == '"' then
return s
end
s = s..c
until c == ''
elseif c == '-' or is_digit(c) then
local s = c
repeat
c = input()
local d = is_digit(c)
if d then
s = s..c
end
until not d
input(true)
return tonumber(s)
elseif c == '{' then
local arr = {}
local elem
repeat
elem = read_from_string(input)
table.insert(arr, elem)
until not elem
return arr
end
end
local data_string = '{-42, "top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}'
local obj = read_from_string(data_string)
-- obj == {-42, "top", {"one", {"one a", "one b"}}, {"two", {"two a", "two b"}}}
Strings must be enclosed in " and must not contain character \ inside. String may be empty.
Numbers must be integer in decimal notation with optional minus.
Arrays must contain only strings, numbers and subarrays. Array may be empty.

How to return a table with string keyed key value pairs from a lua script to node js?

I have a lua script. I am running from node.js and my script is returning a lua table with key value pairs in it like { '1': 15, '2': 35 }. In node I am getting an empty array. However if I return arrayName['1']. It gives me proper value 15. What am I doing wrong here. I am using node_redis client for node to redis. Diffrent files are given below.
Lua Script - groupBy.lua
local db = "";
local table = "students";
local groupBy = "class";
local aggregate = "marks";
local a = {};
local marksGroupedByClass = {};
for i = 1, 4 do
local dataArr = redis.call("hgetall", db..table..":"..i);
local dataObj = {};
for i = 1, #dataArr, 2 do
dataObj[dataArr[i]] = dataArr[i+1];
end
if a[dataObj["class"]] then
a[dataObj["class"]] = a[dataObj["class"]] + dataObj["marks"]
else
a[dataObj["class"]] = dataObj["marks"]
end
end
return a['2']; -- This returns proper value 35
-- return a; This returns empty array to node
node file - luaExec.js
let fs = require('fs');
let redis = require('redis');
let client = redis.createClient();
client.on("error", cb);
function cb(err) {
console.log("Error " + err);
}
client.eval(fs.readFileSync('groupBy.lua'), 0, (err, replies) => {
if(err) cb(err);
console.log(replies);
})
client.quit();
I saved my data with this script - saveStudentData.lua
redis.call("hmset","students:1", "name", "A", "class", 1, "marks", 5 );
redis.call("hmset","students:2", "name", "B", "class", 1, "marks", 10 );
redis.call("hmset","students:3", "name", "C", "class", 2, "marks", 15 );
redis.call("hmset","students:4", "name", "D", "class", 2, "marks", 20 );
TL;DR you can't.
Redis has no support for a key-value type of response (although there are talks of changing that in the next version of the protocol RESP3).
Thus, returning an associative array from Lua (a table with kv pairs) results in an empty array as you've found out. What you'll need to do is flatten it, e.g.:
...
local reply = {} for k, v in pairs(a) do
table.insert(reply, k)
table.insert(reply, v)
end
return reply
Or simply prepare a flattened in the preceding loop. Lastly, your client will have to be aware of this format and recompose the object from it, should that be needed.

Create multidimentional array in swift with different datatypes

this is my first question here so forgive me if it is not very clear.
I am trying to create an array in swift that will store either arrays of arrays or an integer number.
The array is supposed to be a simple representation of the data I will be using which is basically a tree kind of data structure like so...
Array = [ [[ [2, 3] ], [ 1, 4 ], [ 2 ]],
[ 2 ], [[2, 5], [6, 1] ], 3 ]
In overall the arrays are the branches and the integers are the leaves
I've tried declaring them as optionals like so
var test2 = [[[Int]?]?]()
Or using typedef's but I still can't get it to work.
Also, it should be possible to add new leaves to any of the arrays
Here is a solution based on enum, first declare the enum:
enum Node
{
case leaf(Int)
case branch([Node])
}
You can now write things such as:
let x = Node.leaf(42)
let y = Node.branch([Node.leaf(42), Node.leaf(24)])
However this is going to become laborious very quickly. Fortunately Swift allows conversions from literals, so we add:
extension Node : ExpressibleByIntegerLiteral
{
init(integerLiteral value: Int)
{
self = .leaf(value)
}
}
extension Node : ExpressibleByArrayLiteral
{
init(arrayLiteral elements: Node...)
{
self = .branch(elements)
}
}
And with those added we can now write the above two let statements as:
let x : Node = 42
let y : Node = [42, 24]
which is nicer. However if we print(y) we get:
branch([Node.leaf(42), Node.leaf(24)])
If you wish to pretty print that you can add:
extension Node : CustomStringConvertible
{
var description : String
{
switch self
{
case .leaf(let value):
return value.description
case .branch(let branches):
return branches.description
}
}
}
And now print(y) gives you:
[42, 24]
Finally your example:
let w : Node = [[[[2, 3]], [1, 4], [2]], [2], [[2, 5], [6, 1]], 3]
which prints as:
[[[[2, 3]], [1, 4], [2]], [2], [[2, 5], [6, 1]], 3]
You'll want to complete the enum type, with predicates such as isLeaf etc., but that is the basic idea.
HTH

Use a string of expressions in a method for python

For example, if I have the string:
"id=100 id2=200 id3=300 ..."
where the variable names, values, and number of expressions can be anything.
How can I then use that string in a method that is used like this:
method(id=100,id2=200,id3=300,...)
I get the string from a command line argument.
We parse them iteratively:
pairs = "id=100 id2=200 id3=300".split(' ')
res = {}
for p in pairs:
k,v = p.rsplit('=', 1)
res[k] = v
print res # prints {'id2': '200', 'id': '100', 'id3': '300'}
# now we can send the dictionary to the method
You can first convert it to a dictionary:
>>> s = "id=100 id2=200 id3=300"
>>> d = dict(a.split('=') for a in s.plit())
>>> print d
{'id2': '200', 'id': '100', 'id3': '300'}
And now use it in functions:
>>> method(**d)

Resources