search in multidimensional array if value is true or false - ruby

I have a multidimensional array looks like as below
{
patient: {
value: 66,
entry_date: "2017-01-17",
source: "self entered",
risk_level: nil,
risk_ranges: [{
level: "low",
is_active: false,
range_low: 80,
range_high: 139,
unit: "mg/dL"
}, {
level: "moderate",
is_active: false,
range_low: 140,
range_high: 199,
unit: "mg/dL"
}, {
level: "high",
is_active: false,
range_low: 200,
range_high: nil,
unit: "mg/dL"
}]
}
}
I want to find out if is_active is false in the risk_ranges array.
Of course I can access to patient.risk_ranges[0].is_active, patient.risk_ranges[1].is_active and patient.risk_ranges[2].is_active but wondering if there's a better way to write this.
if the is_active is false in all 3 objects in array then set patient.risk_level = high
How can I do that?

You can do something along the lines of
if patient.risk_ranges.all?{ |range| range.is_active == false}
patient.risk_level = "high"
end

Related

nativescript-couchbase-plugin querying

I'm trying to use nativescript-couchbase-plugin.
Here is my code:
whereArray.push({ property: "type_id", comparison: "equalTo", value: typeId });
return itemsDb.query({
select: [],
where: whereArray,
order: [{property: "rating", direction: "desc"}],
limit: this.PAGE_SIZE,
offset: page * this.PAGE_SIZE
});
Everything works fine: condition in where clause, ordering, limit and offset.
But I want to add something new to my condition and I'm trying to do this:
whereArray.push({ property: "title", comparison: "like", value: "some name"});
or
whereArray.push({ property: "filters", comparison: "in", value: [1,2,3]});
And these cases don't work. Neither of them. The only one that works is the first one with type_id
So the question is - how to use where array to query corresponding data?
Data Sample:
{
"type_id": 2,
"title": "some name",
"regionId": 372,
"uid": 16177,
"filters": [
1,
2,
3
]
},
P.S. There is an issue inside original repository. But it has no activity at all.
I must agree the plugin documentation could be better. But if you go through the TypeScript declaration, you will find the issue with your code.
When you are adding multiple where conditions, you must include a logical operator.
import {
Couchbase,
QueryLogicalOperator,
QueryComparisonOperator
} from "nativescript-couchbase-plugin";
const database = new Couchbase("my-database");
// Insert docs for testing
const documentId = database.createDocument({
type_id: 2,
title: "some name",
regionId: 372,
uid: 16177,
filters: [1, 2, 3]
});
console.log(documentId);
// Query
const results = database.query({
select: [],
where: [
{
property: "type_id",
comparison: "equalTo",
value: 2,
logical: QueryLogicalOperator.AND
},
{
property: "filters",
comparison: "in",
value: [1, 2, 3]
}
],
order: [{ property: "rating", direction: "desc" }],
limit: 10
});
console.log(results);

How to concatenate differents values for one keys

I have a trouble for several days and I need help to solve it.
I have an hash with multiple values for the same key :
{"answers":
[
{"id":1,"value":true},
{"id":3,"value":false},
{"id":2,"value":3},
{"id":1,"value":false},
{"id":2,"value":false},
{"id":2,"value":1}
]
}
I want a method to group all the values for one key, as an exemple :
{
"answers": [
{
"id":1, "value": [true, false]
},
{
"id":3, "value": [false]
},
{
"id":2, "value":[3, false, 1]
}
]
}
I've tried with the reduce method, but I cant find a way to link values to keys.
Anyone can help me with that ?
Thanks!
It looks like you want Enumerable#group_by to regroup the array of hashes by the :id key in each hash.
This method takes the answers array and returns a new, transformed answers array:
def transform_answers(answers)
answers
.group_by { |h| h[:id] }
.each_value { |a| a.map! { |h| h[:value] } }
.map { |id, value| { id: id, value: value } }
end
You can use it like this:
hash = {
answers: [
{ id: 1, value: true },
{ id: 1, value: false },
{ id: 2, value: 3 },
{ id: 2, value: false },
{ id: 2, value: 1 },
{ id: 3, value: false }
]
}
transformed_answers = transform_answers(hash[:answers]) # => [{:id=>1, :value=>[true, false]}, {:id=>2, :value=>[3, false, 1]}, {:id=>3, :value=>[false]}]
You can easily take the transformed answers and put them back into a hash resembling the original input:
transformed_hash = { answers: transformed_answers }
hash = {
answers: [
{ id: 1, value: true },
{ id: 1, value: false },
{ id: 2, value: 3 },
{ id: 2, value: false },
{ id: 2, value: 1 },
{ id: 3, value: false }
]
}
def doit(answers)
answers.each_with_object({}) do |g,h|
h.update(g[:id]=>{ id: g[:id], value: [g[:value]] }) do |_,o,n|
{ id: o[:id], value: o[:value]+n[:value] }
end
end.values
end
{ answers: doit(hash[:answers]) }
#=> {:answers=>[
# {:id=>1, :value=>[true, false]},
# {:id=>2, :value=>[3, false, 1]},
# {:id=>3, :value=>[false]}
# ]
# }
This uses the form of Hash#update (aka merge!) that employs a block to determine the values of keys that are present in both hashes being merged. That block is
do |_k,o,n|
{ id: o[:id], value: o[:value]+n[:value] }
end
See the doc for update for definitions of the three block variables, _k, o and n. I've written the first block variable (the common key) _k, rather than k, to signify that it is not used in the block calculation.
Note that before values is executed in doit the method has constructed the following hash.
{1=>{:id=>1, :value=>[true, false]},
2=>{:id=>2, :value=>[3, false, 1]},
3=>{:id=>3, :value=>[false]}}

Rethink db order by optional field

Docs:
[{
id: 111,
weight: 1
},{
id: 222,
},{
id: 333,
weight: -1
}]
I want to order the docs by weight if weight not exists treat its weight as 0
How can I do that ?
You can use function as mentioned here with default:
r.table(TABLE_NAME).orderBy(r.asc(function(doc) {
return doc("weight").default(0)
}));

Ruby, unique hashes in array based on multiple fields

I'd like to get back an array of hashes based on sport and type combination
I've got the following array:
[
{ sport: "football", type: 11, other_key: 5 },
{ sport: "football", type: 12, othey_key: 100 },
{ sport: "football", type: 11, othey_key: 700 },
{ sport: "basketball", type: 11, othey_key: 200 },
{ sport: "basketball", type: 11, othey_key: 500 }
]
I'd like to get back:
[
{ sport: "football", type: 11, other_key: 5 },
{ sport: "football", type: 12, othey_key: 100 },
{ sport: "basketball", type: 11, othey_key: 200 },
]
I tried to use (pseudocode):
[{}, {}, {}].uniq { |m| m.sport and m.type }
I know I can create such array with loops, I'm quite new to ruby and I'm curious if there's a better (more elegant) way to do it.
Try using Array#values_at to generate an array to uniq by.
sports.uniq{ |s| s.values_at(:sport, :type) }
One solution is to build some sort of key with the sport and type, like so:
arr.uniq{ |m| "#{m[:sport]}-#{m[:type]}" }
The way uniq works is that it uses the return value of the block to compare elements.
require 'pp'
data = [
{ sport: "football", type: 11, other_key: 5 },
{ sport: "football", type: 12, othey_key: 100 },
{ sport: "football", type: 11, othey_key: 700 },
{ sport: "basketball", type: 11, othey_key: 200 },
{ sport: "basketball", type: 11, othey_key: 500 }
]
results = data.uniq do |hash|
[hash[:sport], hash[:type]]
end
pp results
--output:--
[{:sport=>"football", :type=>11, :other_key=>5},
{:sport=>"football", :type=>12, :othey_key=>100},
{:sport=>"basketball", :type=>11, :othey_key=>200}]

Load local JSON data in jQgrid without AddJsonRows

I'm using the method addJsonRows to add local data to a jQgrid. As this method disables the sorting I need another solution. One restriction: I can't set the url and fetch the data from the server because the data was passed through another component.
Underneath snippet enlightens the case. The commented line shows the restriction, I replaced it by defining a local variable to have a test case.
<script type="text/javascript" language="javascript">
function loadPackageGrid() {
// Get package grid data from hidden input.
// var data = eval("("+$("#qsmId").find(".qsm-data-packages").first().val()+")");
var data = {
"page": "1",
"records": "2",
"rows": [
{ "id": "83123a", "PackageCode": "83123a" },
{ "id": "83566a", "PackageCode": "83566a" }
]
};
$("#packages")[0].addJSONData(data);
};
$(document).ready(function() {
$("#packages").jqGrid({
colModel: [
{ name: 'PackageCode', index: 'PackageCode', width: "110" },
{ name: 'Name', index: 'Name', width: "300" }
],
pager: $('#packagePager'),
datatype: "local",
rowNum: 10000,
viewrecords: true,
caption: "Packages",
height: 150,
pgbuttons: false,
loadonce: true
});
});
</script>
I wonder how I could do this in an other (better) way to keep the sorting feature.
I tried something with the data option, without result.
I suppose that the same question is interesting for other persons. So +1 from me for the question.
You can solve the problem in at least two ways. The first one you can use datatype: "jsonstring" and datastr: data. In the case you need to add additional parameter jsonReader: { repeatitems: false }.
The second way is to use datatype: "local" and data: data.rows. In the case the localReader will be used to read the data from the data.rows array. The default localReader can read the data.
The corresponding demos are here and here.
I modified a little your data: filled "Name" column and included the third item in the input data.
Now you can use local paging, sorting and filtering/searching of the data. I included a little more code to demonstrate the features. Below you find the code of one from the demos:
$(document).ready(function () {
'use strict';
var data = {
"page": "1",
"records": "3",
"rows": [
{ "id": "83123a", Name: "Name 1", "PackageCode": "83123a" },
{ "id": "83432a", Name: "Name 3", "PackageCode": "83432a" },
{ "id": "83566a", Name: "Name 2", "PackageCode": "83566a" }
]
},
grid = $("#packages");
grid.jqGrid({
colModel: [
{ name: 'PackageCode', index: 'PackageCode', width: "110" },
{ name: 'Name', index: 'Name', width: "300" }
],
pager: '#packagePager',
datatype: "jsonstring",
datastr: data,
jsonReader: { repeatitems: false },
rowNum: 2,
viewrecords: true,
caption: "Packages",
height: "auto",
ignoreCase: true
});
grid.jqGrid('navGrid', '#packagePager',
{ add: false, edit: false, del: false }, {}, {}, {},
{ multipleSearch: true, multipleGroup: true });
grid.jqGrid('filterToolbar', { defaultSearch: 'cn', stringResult: true });
});
UPDATED: I decided to add more details about the differences between datatype: "jsonstring" and datatype: "local" scenarios because the old answer be read and voted by many readers.
I suggest to modify the above code a little to show better the differences. The fist code uses datatype: "jsonstring"
$(function () {
"use strict";
var data = [
{ id: "10", Name: "Name 1", PackageCode: "83123a", other: "x", subobject: { x: "a", y: "b", z: [1, 2, 3]} },
{ id: "20", Name: "Name 3", PackageCode: "83432a", other: "y", subobject: { x: "c", y: "d", z: [4, 5, 6]} },
{ id: "30", Name: "Name 2", PackageCode: "83566a", other: "z", subobject: { x: "e", y: "f", z: [7, 8, 9]} }
],
$grid = $("#packages");
$grid.jqGrid({
data: data,
datatype: "local",
colModel: [
{ name: "PackageCode", width: 110 },
{ name: "Name", width: 300 }
],
pager: "#packagePager",
rowNum: 2,
rowList: [1, 2, 10],
viewrecords: true,
rownumbers: true,
caption: "Packages",
height: "auto",
sortname: "Name",
autoencode: true,
gridview: true,
ignoreCase: true,
onSelectRow: function (rowid) {
var rowData = $(this).jqGrid("getLocalRow", rowid), str = "", p;
for (p in rowData) {
if (rowData.hasOwnProperty(p)) {
str += "propery \"" + p + "\" + have the value \"" + rowData[p] + "\n";
}
}
alert("all properties of selected row having id=\"" + rowid + "\":\n\n" + str);
}
});
$grid.jqGrid("navGrid", "#packagePager",
{ add: false, edit: false, del: false }, {}, {}, {},
{ multipleSearch: true, multipleGroup: true });
$grid.jqGrid("filterToolbar", { defaultSearch: "cn", stringResult: true });
});
It displays (see the demo)
One can see unsorted items in the same order like input data. The items of input data will be saved in internal parameters data and _index. getLocalRow method used in onSelectRow shows that items of internal data contains only properties of input items which names corresponds to name property of some jqGrid columns. Additionally unneeded _id_ property will be added.
On the other side the next demo which uses datatype: "local" displays sorted data and all properties inclusive complex objects will be still saved in the internal data:
The code used in the last demo is included below:
$(function () {
"use strict";
var data = [
{ id: "10", Name: "Name 1", PackageCode: "83123a", other: "x", subobject: { x: "a", y: "b", z: [1, 2, 3]} },
{ id: "20", Name: "Name 3", PackageCode: "83432a", other: "y", subobject: { x: "c", y: "d", z: [4, 5, 6]} },
{ id: "30", Name: "Name 2", PackageCode: "83566a", other: "z", subobject: { x: "e", y: "f", z: [7, 8, 9]} }
],
$grid = $("#packages");
$grid.jqGrid({
data: data,
datatype: "local",
colModel: [
{ name: "PackageCode", width: 110 },
{ name: "Name", width: 300 }
],
pager: "#packagePager",
rowNum: 2,
rowList: [1, 2, 10],
viewrecords: true,
rownumbers: true,
caption: "Packages",
height: "auto",
sortname: "Name",
autoencode: true,
gridview: true,
ignoreCase: true,
onSelectRow: function (rowid) {
var rowData = $(this).jqGrid("getLocalRow", rowid), str = "", p;
for (p in rowData) {
if (rowData.hasOwnProperty(p)) {
str += "propery \"" + p + "\" + have the value \"" + rowData[p] + "\"\n";
}
}
alert("all properties of selected row having id=\"" + rowid + "\":\n\n" + str);
}
});
$grid.jqGrid("navGrid", "#packagePager",
{ add: false, edit: false, del: false }, {}, {}, {},
{ multipleSearch: true, multipleGroup: true });
$grid.jqGrid("filterToolbar", { defaultSearch: "cn", stringResult: true });
});
So I would recommend to use datatype: "local" instead of datatype: "jsonstring". datatype: "jsonstring" could have some advantages only in some very specific scenarios.
Great advice, Oleg.
In my web app, I pre-loaded some JSON data which looked like this:
{
WorkflowRuns:
[
{
WorkflowRunID: 1000,
WorkflowRunName: "First record",
},
{
WorkflowRunID: 1001,
WorkflowRunName: "Second record",
}
],
UserInformation:
{
Forename: "Mike",
Surname: "Gledhill"
}
}
And here's the code I needed to create the jqGrid, just based on the WorkflowRuns part of this JSON:
var JSONstring = '{ WorkflowRuns: [ { WorkflowRunID: 1000, .. etc .. } ]';
$("#tblWorkflowRuns").jqGrid({
datatype: "local",
data: JSONstring.WorkflowRuns,
localReader: {
id: "WorkflowRunID",
repeatitems: false
},
...
});
This was a bit of trial and error though.
For example, jqGrid seemed to ignore datastr: JSONstring for me.
And notice how, with local data, I needed to use localReader, rather than jsonReader, otherwise it wouldn't set the row IDs properly.
Hope this helps.

Resources