I have raw data that is contained in 3 separate lines. I want to build a single map record using parts of each line. I then read the next 3 lines and create the next map record and so on. All the groovy examples I've found on maps show them being created from data on a single line, or possibly i am misunderstanding the examples. Here is what the raw data looks like.
snmp v2: data result = "Local1"
snmp v2: data result ip = "10.10.10.121"
snmp v2: data result gal = "899"
new
snmp v2: data result = "Local2"
snmp v2: data result ip = "192.168.10.2"
snmp v2: data result gal = "7777"
new
I want to put this data into a map. In this example Local1 and Local2 would be keys and they would each have 2 associated values. I will show you my latest attempt but it is little more then a guess that failed.
def data = RAW
def map = [:]
data.splitEachLine("="){
it.each{ x ->
map.put(it[0], it[1])
map.each{ k, v -> println "${k}:${v}" } }}
The desired output is:
[ Local1 : [ ip: "10.10.10.121", gal: "899" ],
Local2: [ ip: "192.168.10.2", gal: "7777" ] ]
You can build a new data structure from an existing one using aggregate operations defined on collections; collect produces a list from an existing list, collectEntries creates a map from a list.
The question specifies there are always three lines for an entry, followed by a line with "new" on it. If I can assume they're always in the same order I can grab the last word off each line, use collate to group every four lines into a sublist, then convert each sublist to a map entry:
lines = new File('c:/temp/testdata.txt').readLines()
mymap = lines.collect { it.tokenize()[-1] }
.collate(4)
.collectEntries { e-> [(e[0].replace('"', ''))) : [ip: e[1], gal: e[2]]] }
which evaluates to
[Local1:[ip:"10.10.10.121", gal:"899"], Local2:[ip:"192.168.10.2", gal:"7777"]]
or remove all the quotes in the first step:
mymap = lines.collect { (it.tokenize()[-1]).replace('"', '') }
.collate(4)
.collectEntries { e-> [(e[0]) : [ip: e[1], gal: e[2]]] }
in order to get
[Local1:[ip:10.10.10.121, gal:899], Local2:[ip:192.168.10.2, gal:7777]]
If you want to get a nested map as suggested by dmahapatro try this:
def map = [:]
data=data.eachLine() { line ->
if(line.startsWith("new")) return
tokens=line.replace("snmp v2: data","").split("=")
tokens=tokens.collect() { it.trim().replace("result ","").replaceAll(/"/, "") }
if(tokens[0]=="result") {
nested=[:]
map[tokens[1]]=nested
}
else
nested[tokens[0]]=tokens[1]
}
println("map: $map")
here we:
iterate over lines
skip lines with "new" at the beginning
remove "snmp v2: data" from the text of the line
split each line in tokens, trim() each token, and remove "result " and quotes
tokens are in pairs and now look like:
result, Local1
ip, 10.10.10.121
gal, 899
next when the first token is "result", we build a nested map and place in the main map at the key given by the value of token[1]
otherwise we populate the nested map with key=token[0] and value=token[1]
the result is:
map: [Local1:[ip:10.10.10.121, gal:899], Local2:[ip:192.168.10.2, gal:7777]]
edit: fixed to remove quotes
Related
I have identified 3-5 keywords for every requirement in module-A. Each keyword is separated by a comma. Now I want to search every requirement in module-B to see which of them have words that match each of the key words.
Not sure exactly what you're looking for. You might have to specify if none of these solutions I'm about to propose are exactly what you're looking for.
If you're trying to create a filter which displays only objects with those keywords in your current view, you can create an advanced filter by first going to filter (Tools > Filter > Define) and then select the Advanced button on the bottom left of the filter menu that appears.
At this point you can create custom rules for the filter. I would just create an individual rule for each word with the following definition:
Attribute: Object Text
Condition: contains
Value: <insert word here>
Match Case: uncheck
Regular Expression: uncheck
Then select the Add button to add the rule to the list of available rules in the Advanced Options.
At this point you can select multiple rules in the list of available rules and you can AND/OR these rules together to create a custom filter for the view that you want.
So that's for if you're trying to create a custom view with just objects containing specific words.
If you're talking about writing DXL code to automatically spit out requirements that have a particular word in it. You can use the something that looks like this:
Object o
String s
int offset, len
for o in entire (current Module) do
{
if (isDeleted(o)) continue
s = o."Object Text"""
if findPlainText(s, "<insert word here>", offset, len, false)
{
print identifier(o) // or replace this line with however you want to display object
}
}
Hope this is helpful. Cheers!
Edit:
To perform actions on a comma separated list, one at a time, you can use a while loop with some sort of search function that cuts off words one at a time.
void processWord (string someWord, Module mTarget, Object oSource)
{
Object oTarget
string objID = identifier(oSource)
for oTarget in mTarget do
{
if (<someWord in oTarget Object Text>) // edit function as necessary to do this
{
if (oTarget."Exists""" == "")
oTarget."Exists" = objID
else
oTarget."Exists" = oTarget."Exists" "," objID
}
}
}
int offset, len
string searchCriteria
Module mSource = read("<path of source module>", true)
Module mTarget = edit("<path of target module>", true)
Object oSource
for oSource in mSource do // can use "for object in entire(m)" for all objects
{
if (oSource != rqmt) continue // create conditions specific to your module here
searchCriteria = oSource."Search Criteria"""
while (findPlainText(searchCriteria, ",", offset, len, false))
{
processWord(searchCriteria[0:offset-1], mTarget, oSource)
searchCriteria = searchCriteria[offset+1:]
}
}
processWord(searchCriteria, mTarget, oSource) // for last value in comma separated list
In order to automate our reporting, we want to convert Google Sheets cells to dynamic fields that we can use in a pre-written text. We think this is possible with Zapier.
We currently have the following code:
import csv
import requests
from csv import reader
result = []
url = input_data['csvlink']
stats = requests.get(url)
content = stats.content.decode('iso-8859-1')
for line in csv.reader(content.splitlines()):
result.append(line)
values = { i : result[i] for i in range(0, len(result) ) }
return values
However, this code returns a dictionary with the CSV row numbers as keys, and the data of the entire corresponding row as its value.
How can we return a dictionary with a key for every unique data point in the CSV?
Great question!
This is another case of the computer correctly doing exactly what you told it to. Namely in:
values = { i : result[i] for i in range(0, len(result) ) }
You say that values should be an dict where each key is a number and the value is the csv line at that index in the results.
In the comments, you mentioned wanting the entire CSV. Try something like:
from string import ascii_uppercase
result = {}
# your CSV code goes here. The data should be in `lines`, not `result`
for num_row, line in enumerate(lines):
for num_column, col in enumerate(line):
result[ascii_uppercase[num_column] + str(num_row + 1)] = col
return result
This will work as long as there are fewer than 26 columns. This won't do AA, AB, but that would be possible with more code if you need it.
I tried many things but of no use.
I have already raised a question on stackoverflow earlier but I am still facing the same issue.
Here is the link to old stackoverflow question
creating multiple nodes with properties in json in neo4j
Let me try out explaining with a small example
This is the query I want to execute
{
"params" : {
"props" : [
{
"LocalAsNumber" : 0,
"NodeDescription" : "10TiMOS-B-4.0.R2 ",
"NodeId" : "10.227.28.95",
"NodeName" : "BLR_WAO_SARF7"
}
]
},
"query" : "MATCH (n:Router) where n.NodeId = {props}.NodeId RETURN n"}
For simplicity I have added only 1 props array otherwise there are around 5000 props. Now I want to execute the query above but it fails.
I tried using (props.NodeId}, {props[NodeID]} but everything fails.
Is it possbile to access a individual property in neo4j?
My prog is in c++ and I am using jsoncpp and curl to fire my queries.
If you do {props}.nodeId in the query then the props parameter must be a map, but you pass in an array. Do
"props" : {
"LocalAsNumber" : 0,
"NodeDescription" : "10TiMOS-B-4.0.R2 ",
"NodeId" : "10.227.28.95",
"NodeName" : "BLR_WAO_SARF7"
}
You can use an array of maps for parameter either with a simple CREATE statement.
CREATE ({props})
or if you loop through the array to access the individual maps
FOREACH (prop IN {props} |
MERGE (i:Interface {nodeId:prop.nodeId})
ON CREATE SET i = prop
)
Does this query string work for you?
"MATCH (n:Router) RETURN [p IN {props} WHERE n.NodeId = p.NodeId | n];"
I have a Grails command object with a list of maps. The map key is intended to be a numeric domain object ID.
class MyCommand {
def grid = [].withDefault { [:] }
}
Data binding to the list/map is working in general because of the dynamic list expansion.
However, in the POST, the map keys are being bound as Strings and I want them to be Longs, as they are when the form is initially populated. I want foo[123] in my map, not foo['123'].
Alternatively I would be satisfied if the [] operators found the correct value given a numeric ID key to look up. In other words, if I could get foo[123] to return the same value as foo['123'], that would work too.
Any way to get this to work the way I want to? Maybe strongly type the map?
Or a better approach?
You can inject the property into the map to convert a String key to Long. For example:
def myMap = [:] << ['1': "name"] << ['Test': "bobo"]
def result = myMap.inject([:]){map, v ->
def newKey = v.key.isNumber() ? v.key.toLong() : v.key
map[newKey] = v.value
map
}
assert myMap['1'] == 'name'
assert result[1L] == 'name'
assert result['Test'] == 'bobo'
Just picking upon Lua and trying to figure out how to construct tables.
I have done a search and found information on table.insert but all the examples I have found seem to assume I only want numeric indices while what I want to do is add key pairs.
So, I wonder if this is valid?
my_table = {}
my_table.insert(key = "Table Key", val = "Table Value")
This would be done in a loop and I need to be able to access the contents later in:
for k, v in pairs(my_table) do
...
end
Thanks
There are essentially two ways to create tables and fill them with data.
First is to create and fill the table at once using a table constructor. This is done like follows:
tab = {
keyone = "first value", -- this will be available as tab.keyone or tab["keyone"]
["keytwo"] = "second value", -- this uses the full syntax
}
When you do not know what values you want there beforehand, you can first create the table using {} and then fill it using the [] operator:
tab = {}
tab["somekey"] = "some value" -- these two lines ...
tab.somekey = "some value" -- ... are equivalent
Note that you can use the second (dot) syntax sugar only if the key is a string respecting the "identifier" rules - i.e. starts with a letter or underscore and contains only letters, numbers and underscore.
P.S.: Of course you can combine the two ways: create a table with the table constructor and then fill the rest using the [] operator:
tab = { type = 'list' }
tab.key1 = 'value one'
tab['key2'] = 'value two'
Appears this should be the answer:
my_table = {}
Key = "Table Key"
-- my_table.Key = "Table Value"
my_table[Key] = "Table Value"
Did the job for me.