Sorting JSON data in Ruby - arrays

I have following JSON structure:
{
"name": "MessageEnvelope",
"type": "record",
"fields": [
{
"name": "message",
"type":
{
"name": "Message",
"type": "record",
"fields": [
....
]
}
},
{
"name": "pipeline_system",
"type": {
"type": "enum",
"name": "PipelineSystem",
"symbols": [ "enterprise", "backscoring", "compliance" ]
}
},
{
"name": "batch_id",
"type": [ "null", "string" ]
}
]
}
I am looking to sort the above JSON file as best as it could be. For example:
fields : [
{
"name": "batch_id",
"type": [ "null", "string" ]
},
...
...
{
"name": "pipeline_system",
"type": {
"type": "enum",
"name": "PipelineSystem",
"symbols": [ "backscoring", "compliance", "enterprise" ]
}
}
Like it sorts the internal arrays as well as hashes. I am trying to write following:
def sort(collection)
if collection.is_a?(Hash)
puts "Hash Object...."
if(collection["type"]=="record")
puts "record found... Type = #{collection["fields"].class}";
if collection["fields"].is_a?(Array)
puts "fields type is array...." #we can sort fields arrays on the basis of name
collection["fields"].sort_by{|arrayCollectionElement| arrayCollectionElement["name"] }
arrayCollection = collection["fields"] #this is array of hash...we can sort them on the basis of name..done above in sort by...
puts "class = #{arrayCollection.class}"
puts "sorted fields: #{arrayCollection}"
end
end #else it is again a hash
end
collection
end
but it is not sorting the fields array on the basis of names.
Appreciate any possible help!

If I properly understood the requirements:
json = '...'
require 'json'
hash = JSON.parse json
# ⇓ let’s sort the array of fields inplace
hash['fields'].sort_by! { |o| o['name'] }
hash
#⇒ {
# "fields" => [
# [0] {
# "name" => "batch_id",
# "type" => [ "null", "string" ]
# },
# [1] {
# "name" => "message",
# "type" => {
# "fields" => [],
# "name" => "Message",
# "type" => "record"
# }
# },
# [2] {
# "name" => "pipeline_system",
# "type" => {
# "name" => "PipelineSystem",
# "symbols" => [ "enterprise", "backscoring", "compliance" ],
# "type" => "enum"
# }
# }
# ],
# "name" => "MessageEnvelope",
# "type" => "record"
# }
To sort all arrays inside, one might introduce a recursive function:
def sort_arrays hash
hash.each do |_, v|
case v
when Array then v.sort!
when Hash then sort_arrays v
end
end
end
and call it on the topmost hash.

Related

Change property name when converting Powershell object to JSON using ConvertTo-Json?

I have a dataset consisting of a two-dimensional array (flexData[5][2]). I have this defined in my Powershell script as follows:
class flexData {
[DateTime]$dateTime
[string]$firmwareVersion
[string[][]]$flexData
}
$flexObj = [flexData]#{dateTime = $(Get-Date); firmwareVersion = 'u031C'; flexData = #(#(0, 1), #(320, 17), #(45, 36), #(0, 0))}
The problem with this is that the output object that ConvertTo-Json spits out is hard to read:
{
"dateTime": "2021-10-11T13:58:25.0937842+02:00",
"firmwareVersion": "u031C",
"flexData": [
[
"0",
"1"
],
[
"320",
"17"
],
[
"45",
"36"
],
[
"0",
"0"
]
]
}
Is there a way to instead of using a single key name and two-dimensional arrays, to instead convert this to flexData0, flexData1 ... flexData4 and keep my actual data as single-dimensional arrays? I could obviously do this by manually defining my class as:
class flexData {
[DateTime]$dateTime
[string]$firmwareVersion
[string[]]$flexData0
[string[]]$flexData1
[string[]]$flexData2
[string[]]$flexData3
[string[]]$flexData4
}
But is there a smarter way of doing this? Especially since I would also like to make a third-dimension of my array to store multiple iterations of flexData?
You could add a constructor to your flexData class that creates an object from the top-level array instead:
class flexData {
[DateTime]$dateTime
[string]$firmwareVersion
[psobject]$flexData
flexData([DateTime]$dateTime, [string]$firmwareVersion, [string[][]]$flexData){
$this.dateTime = $dateTime
$this.firmwareVersion = $firmwareVersion
# Create object from nested array
$dataProperties = [ordered]#{}
for($i = 0; $i -lt $flexData.Length; $i++){
$dataProperties["$i"] = $flexData[$i]
}
$this.flexData = [pscustomobject]$dataProperties
}
}
Now, the individual outer array items will be listed as properties named 0 through (N-1):
PS ~> $data = [flexData]::new($(Get-Date), 'u031C', #(#(0, 1), #(320, 17), #(45, 36), #(0, 0)))
PS ~> $data |ConvertTo-Json
{
"dateTime": "2021-10-11T14:21:48.4026882+02:00",
"firmwareVersion": "u031C",
"flexData": {
"0": [
"0",
"1"
],
"1": [
"320",
"17"
],
"2": [
"45",
"36"
],
"3": [
"0",
"0"
]
}
}

Return document where array element includes all values of input array | MongoDB

I have a collection of exercises:
[
{
"name": "Push Ups",
"muscleGroups": ["Chest", "Shoulders", "Abs", "Biceps"]
},
{
"name": "Sit Ups",
"muscleGroups": ["Abs"]
},
{
"name": "Pull Ups",
"muscleGroups": ["Abs", "Biceps", "Back"]
}
]
and an input array of inputMuscleGroups. I am trying to filter the exercises to where the muscleGroups array of the document has every element of the inputMuscleGroups.
For inputMuscleGroups = ["Abs"], every document would return.
For inputMuscleGroups = ["Abs", "Biceps"], output would be:
[
{
"name": "Push Ups",
"muscleGroups": ["Chest", "Shoulders", "Abs", "Biceps"]
},
{
"name": "Pull Ups",
"muscleGroups": ["Abs", "Biceps", "Back"]
}
]
For inputMuscleGroups = ["Abs", "Shoulders", "Chest"], output would be:
[
{
"name": "Push Ups",
"muscleGroups": ["Chest", "Shoulders", "Abs", "Biceps"]
}
]
I have played around with $in but it appears these only return true if any of the input arrays match any of the document array.
Ideally I would want to do this within a .find() method as opposed to a .aggregate() method.
You can simply use $all
db.collection.find({
muscleGroups: {
$all: [
"Abs",
"Biceps"
]
}
})
Working Mongo playground

Get the value of 2nd index by mapping 1st index through Hash of Arrays in Perl

I have a Perl file code state.pl where I am trying to retrieve full name of State based on State code from Hash of Arrays. Following is the code:
my $all_state_details = {
IN => [
[
"AP",
"Andhra Pradesh"
],
[
"AN",
"Andaman and Nicobar Islands"
],
[
"AR",
"Arunachal Pradesh"
],
],
US => [
[
"AL",
"Alabama"
],
[
"AK",
"Alaska"
],
[
"AS",
"American Samoa"
],
],
};
my $state = 'AN';
my $country = 'IN';
my #states = $all_state_details->{$country};
my #state_name = grep { $_->[0] eq $state } #states;
print #state_name;
When I run the script, I get the blank output
I want the output as just:
Andaman and Nicobar Islands
The #{ ... } dereference operation is necessary to convert the array reference in $all_state_details->{$country} into an array suitable for use with grep.
print map { $_->[1] }
grep { $_->[0] eq $state } #{$all_state_details->{$country}};
The right way to do this kind of lookup is with a hash of hashes.
e.g.
%all_state_details = (
IN => {
"AP" => "Andhra Pradesh",
"AN" => "Andaman and Nicobar Islands",
},
);
Then you just do a direct lookup.
print $all_state_details{IN}{AN};
Read https://perldoc.perl.org/perldsc.html#HASHES-OF-HASHES
HTH

How to add text in an array using fs?

I have a json array called "names" for a poll, I have already the input but I need to store the name inside the array "names" using fs, I have tried to search on google and stack overflow how to but nothing worked for me
Before
{
"names": [
"test",
"test2"
],
...
}
After
{
"names": [
"test",
"test2",
"test3"
],
...
}
let name_list = {
"names": [
"test",
"test2"
]
}
function addName(name)
{
arr_name = name_list.names
arr_name.push(name)
}
addName('test3')
console.log(name_list);

Find array in array data in MongoDB

I want find in this document groups:
"document": {
"groups": [
{
"id": "5ccd5f7f34f82b0e3315b2f6"
},
{
"id": "73b43unbfkfmdmddfdf84jjk"
}
]
}
are contains some of my query array groups ID:
[ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ]
A simple find query suffices:
db.collection.find({ 'groups.id' : {$in : [ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ] }})

Resources