I want a code/some hints of comparison of one array with another array.
If one element of array matches with an element in the other array, return 0 with puts statement, otherwise one with some puts statement.
I try to search on the Internet but can't find any useful stuff.
array set foodColor {
Apple red
Banana yellow
Lemon yellow
Carrot orange
}
array set citrusColor {
Lemon yellow
Orange orange
Lime green
}
# build up a list of non-citrus foods
foreach k [array names citrusColor] {
if {![info exists foodColor($k)]} {
puts $k;
}
}
In this code, output shows those value that does not match with values in other array.
But I don't want character or string comparison in array ,I want full array comparison with the other array if match show output match else not match.
The syntax of array set is as follows,
array set arrayName list
Sets the values of one or more elements in arrayName. list must have a
form like that returned by array get, consisting of an even number of
elements. Each odd-numbered element in list is treated as an element
name within arrayName, and the following element in list is used as a
new value for that array element. If the variable arrayName does not
already exist and list is empty, arrayName is created with an empty
array value.
You should get the following error
wrong # args: should be "array set arrayName list"
The code can be rewritten as,
array set food {
Apple red
Banana yellow
Lemon yellow
Carrot orange
}
array set citrus {
Lemon yellow
Orange orange
Lime green
}
foreach k [array names citrus] {
if {[info exists food($k)]} {
puts "The key '$k' is available in both arrays"
}
}
Output :
The key 'Lemon' is available in both arrays
Do you want this?
if { [info exists citrusColor($key)] &&
[info exists foodColor($key)] &&
$citrusColor($key) eq $foodColor($key)
} {
puts "Key $key is in both arrays with the same value"
return 0
} else {
puts "Key $key is either missing or has a different value"
return 1
}
Related
Original Data
I have the following JSON:
{
"foo":[
"asd",
"fgh"
],
"bar":[
"abc",
"xyz",
"ert"
],
"baz":[
"something"
]
}
Now I want to transform it to a "flat" CSV, such that for every key in my object the list in the value is expanded to n rows with n being the number of entries in the respective list.
Expected Output
foo;asd
foo;fgh
bar;abc
bar;xyz
bar;ert
baz;something
Approaches
I guess I need to use to_entries and then for each .value repeat the same .key for the first column. The jq docs state that:
Thus as functions as something of a foreach loop.
So I tried combining
to_entriesto give the keys and values from my dictionary an accessible name
then build kind of a foreach loop around the .values
and pass the result to #csv
to_entries|map(.value) as $v|what goes here?|#csv
I prepared something that at least compiles here
Don't need to use _entries function, a simple key/value lookup and string interpolation should suffice
keys_unsorted[] as $k | "\($k);\( .[$k][])"
The construct .[$k][] is an expression that first expands the value associated with each key, i.e. .foo and then with object construction, produces multiple results for each key identified and stored in $k variable.
I have input JSON data in a bunch of files, with an IP address as one of the keys. I need to iterate over a the files, and I need to get "stuff" out of them. The IP address is different for each file, but I'd like to use a single jq command to get the data. I have tried a bunch of things, the closest I've come is this:
jq '.facts | keys | keys as $ip | .[0]' a_file
On my input in a_file of:
{
"facts": {
"1.1.1.1": {
"stuff":"value"
}
}
}
it returns the IP address, i.e. 1.1.1.1, but then how do I to go back do something like this (which is obviously wrong, but I hope you get the idea):
jq '.facts.$ip[0].stuff' a_file
In my mind I'm trying to populate a variable, and then use the value of that variable to rewind the input and scan it again.
=== EDIT ===
Note that my input was actually more like this:
{
"facts": {
"1.1.1.1": {
"stuff": {
"thing1":"value1"
}
},
"outer_thing": "outer_value"
}
}
So I got an error:
jq: error (at <stdin>:9): Cannot index string with string "stuff"
This fixed it- the question mark after .stuff:
.facts | keys_unsorted[] as $k | .[$k].stuff?
You almost got it right, but need the object value iterator construct, .[] to get the value corresponding to the key
.facts | keys_unsorted[] as $k | .[$k].stuff
This assumes that, inside facts you have one object containing the IP address as the key and you want to extract .stuff from it.
Optionally, to guard against objects that don't contain stuff inside, you could add ? as .[$k].stuff?. And also you could optionally validate keys against a valid IP regex condition and filter values only for those keys.
I got three different entries "10576.53012.46344.35174" , "10" and "Doc-15" in foreach loop. Out of these 3 entries, i want 10576.53012.46344.35174. How can i verify that current string contains multiple . and numbers.
Im new to TCL, Need suggestion
This is the sort of task that is a pretty good fit for regular expressions.
The string 10576.53012.46344.35174 is matched by a RE like this: ^\d{5}(?:\.\d{5}){3}$ though you might want something a little less strict (e.g., with more flexibility in the number of digits per group — 5 — or the number of groups following a . — 3).
You test if a string matches a regular expression with the regexp command:
if {[regexp {^\d{5}(?:\.\d{5}){3}$} $theVarWithTheString]} {
puts "the regular expression matched $theVarWithTheString"
}
An alternative approach is to split the string by . and check that each group is what you want:
set goodBits 0
set badString 0
foreach group [split $theVarWithTheString "."] {
if {![string is integer -strict $group]} {
set badString 1
break
}
incr goodBits
}
if {!$badString && $goodBits == 4} {
puts "the string was OK"
}
I greatly prefer the regular expression approach myself (with occasional help from string is as appropriate). Writing non-RE validators can be challenging and tends to require a lot of code.
I have a JSON string strcutred like so:
[{"ip":"", "comment":""}, {"ip":"", "comment":""}]
I'm trying to figure out how to remove one of these objects by identification from the IP and/or comment keys.
The closest i've got so far is this:
my $jsn = decode_json('[{"ip":"1.2.3.4", "comment":"one"}, {"ip":"10.10.10.10","comment":"two"}]');
foreach(#{$jsn}){
if($_->{ip} eq '1.2.3.4'){
print "Found!";
splice #{$jsn}, $_, 1;
}
}
I know splice doesn't work in this example. If i could get the index of the object (ideally without a counter), i think i could then remove the correct object.
grep is your friend here. It creates a new list of elements in an existing list that match an expression.
my #filtered = grep { $_->{ip} ne '1.2.3.4' } #$jsn;
I am trying to parse JSON that is coming to me in the form of an array of arrays (think a table of data). The issue is that this table may contain arrays or maps as elements and these elements may by empty. Here is an example:
json <- '[[1,"foo",[],{}],[1,"bar",[1],{"foo":"bar"}]]'
# Result is a list of 2 where each sublist is of length 4
jsonlite::fromJSON(json)
# Result is a character vector of length 6
> unname(unlist(jsonlite::fromJSON(json)))
[1] "1" "foo" "1" "bar" "1" "bar"
So when I try and cast this to a 2 by 4 matrix I am getting the wrong answer. I would like [] to map to the string "[]" and {} to "{}" so I don't lose elements. It is totally fine for me to return the nested array as "[1]" instead of parsing it as a list. To me this seems like I need to tell the json parser to stop recursing and treat the elements as characters at a certain point but I can't figure out how to do this. I'm not tied to the jsonlite package so basically anything is fair game as long as it is not slow.
You could recursively iterate the parsed json to find the empty lists and replace them with the values you want. For example
renameEmptyLists <- function(x) {
if (is.list(x)) {
if( length(x)==0 ) {
return(if(!is.null(names(x))) { "{}" } else {"[]"} )
} else {
return(lapply(x, renameEmptyLists))
}
} else {
x
}
}
jj <- jsonlite::fromJSON(json)
unname(unlist(renameEmptyLists(jj)))
# [1] "1" "foo" "[]" "{}" "1" "bar" "1" "bar"
And to be clear, you where "loosing" them during the unlist(). If you look at the jj object in my example, you will see that the parse correctly identified the empty list and the empty named list.