Getting a selected property from a getter - ecmascript-6

I have an array of containers in my state and I'm trying to setup a getter that splits it into active and inactive containers.
containers: [{
id: '1',
name: 'test container',
image: 'some image',
state: 'running',
status: 'Running'
}, {
id: '2',
name: 'another test container',
image: 'some image',
state: 'stopped',
status: 'Running'
}]
I'm using this to get the array below.
export const x = state => _.partition(state.containers, c => c.state === 'running');
The problem with this is I want it split and assigned to activeContainers and stoppedContainers and then exported.
[
[
{
"id": "1",
"name": "test container",
"image": "some image",
"state": "running",
"status": "Running"
}
],
[
{
"id": "2",
"name": "another test container",
"image": "some image",
"state": "stopped",
"status": "Running"
}
]
]
I've tried using ES6's deconstruction but I think I'm missing something or putting the deconstruction in the wrong place for it to work with Vuex.
export const [activeContainers = [], stoppedContainers = []] = state => _.partition(state.containers, c => c.state === 'running');

Returning functions from a getter
As per the comments go by in the question, it is indeed true that you can't have two properties mapped by a getter. Reading more that you didn't want another getter for the activeContainers and stoppedContainers
After going through the link you shared, I found a way you could still have something very close to a parameterized getter.
Here you can see it in full effect.
getters = {
getContainer: (state) => {
const [activeContainer = [], inactiveContainer = []] = _.partition(state.containers, c => c.state === 'running')
return (container) => {
return (container === 'activeContainer') // returned function
? activeContainer
: inactiveContainer
}
}
}
Here in this getter, I am returning a function, which can accept parameters and get something very close to what you desire.

Related

How to get data of a JSON file (typescript)

Hi I got a bit stuck at trying to understand how to fetch data of a JSON file.
environment.ts:
export const environment = {
production: false,
urlListBooks: "/assets/list-books.json",
urlGetBooks: "/assets/edit-book.json?:id",
urlGetTags: "/assets/edit-book.json?:tags",
urlPostBooks: "/assets/edit-book.json",
urlListTags: "/assets/list-tags.json",
urlPostTags: "/assets/edit-tag.json"
};
edit-book.json:
"book":{
"id": 1,
"title": "The Shining",
"authorId": 1,
"tags": [{"name":"new"}, {"name":"test"}]
},
"authors":[
{
"id": 1,
"prename": "Stephen",
"surname": "King"
},
{
"id": 3,
"prename": "Algernon",
"surname": "Blackwood"
},
{
"id": 4,
"prename": "Edgar Allan",
"surname": "Poe"
},
{
"id": 5,
"prename": "Howard Phillips",
"surname": "Lovecraft"
}
],
"tags":[
{
"name": "new"
},
{
"name": "Horror"
},
{
"name": "Romance"
}
]
}
service:
getBookTags(n: String) Observable<Tag[]>{
return this.http.get<Tag[]>(environment.urlGetTags.)
}
what I want getBookTags(n: String) to do is returning the tags array of the book with title n defined in the edit-book.json (e.g. "tags": [{"name":"new"}, {"name":"Horror"}] ) so that I can later use the function to check which tags a book has and select them.
Your help would be very appreciated :)
Ok I think I've solved this for you, I'm going to walk through my process with you so you understand what the goal is. You can see my solution here: https://codesandbox.io/s/thirsty-minsky-g6959f?file=/assets/edit-book.json:0-752
First thing is that your JSON you provided doesn't really make much sense, it shows multiple authors and just one "book". I think instead you want multiple books. Secondly, it's gotta be wrapped in a curly brace as shown:
{
"books": [
{
"id": 1,
"title": "The Shining",
"authorId": 1,
"tags": [{ "name": "new" }, { "name": "test" }]
},
{
"id": 2,
"title": "The Wendigo",
"authorId": 2,
"tags": [{ "name": "Horror" }]
}
],
"authors": [
{
"id": 1,
"prename": "Stephen",
"surname": "King"
},
{
"id": 3,
"prename": "Algernon",
"surname": "Blackwood"
},
{
"id": 4,
"prename": "Edgar Allan",
"surname": "Poe"
},
{
"id": 5,
"prename": "Howard Phillips",
"surname": "Lovecraft"
}
],
"tags": [
{
"name": "new"
},
{
"name": "Horror"
},
{
"name": "Romance"
}
]
}
Now, in your Typescript code we want to have typings for the json you're going to fetch. This will make your code more readable, it will give you intellisense, and help you catch some errors before you try to run your code. So we are going to go ahead and type the properties of the JSON as follows:
type Tag = {
name: string;
};
type Book = {
id: number;
title: string;
authorId: number;
tags: Tag[];
};
type Author = {
id: number;
prename: string;
surname: string;
};
type BookData = {
books: Book[];
authors: Author[];
tags: Tag[];
};
Basically what I said is we have bookdata which is made up of books, authors, and tags. Books have properties given under type Book, same thing with Author and Tag.
Now for the actual running code, we are going to use the fetch api to get the json data at the url.
async function getBookTags(n: string): Promise<Book[]> {
return fetch(url)
.then<BookData>((res) => res.json())
.then((data) => data.books)
.then((books) => books.filter((b) => doesBookHaveTag(b, n)));
}
First thing we do is fetch the data from the api, this returns a promise which when resolved (this is what .then does) we take the response and parse it for a json. Then when that promise resolves we get the books in the data. Then when that promise resolves we filter in books that have the matching tag.
doesBookHaveTag is just a little helper function I defined:
function doesBookHaveTag(book: Book, n: string): boolean {
// just return if book has at least one tag matching n
return book.tags.some((t) => t.name.toLowerCase() === n.toLowerCase());
}
If you don't understand promises you should watch some videos on it, but basically the browser sends out an http request and then when it resolves it queues a task to execute the function [see endnote] in .then when it has time. So when we want to call your async function and say log all books with the tag "horror" we do it as shown:
getBookTags("horror").then(console.log); // returns the one book.
I hope this makes sense and you can sort of see how to fetch the data, how to handle the promise it returns, and how to type your response. The only thing I'm not sure on is how Angular changes this for you (I'm a react guy), but this is really just non-library specific Javascript/Typescript.
[endnote] when I say function in .then, what I mean is that .then(data => data.books) is passing a function into the .then function. data => data.books is actually a function the same as:
function(data: BookData): Book[] {
return data.books
}

Laravel API resource (Problem with creating exact API)

I want to create an API in the below format. But I am unable to do it. I am using the API resource. I have tried using different queries but I am not getting the exact solution.Please help me.
Thank you
what I have tried
$marks = StudentMarksResource::collection(StudentsMark::whereIn('academic_id',$ids)->whereIn('student_id',$studentid)->get());
my API resource file
public function toArray($request)
{
return [
'exam_type' => $this->exam_type,
'details' => [
/* 'class_id' => Course::find($this->class_id),
'batch_id' => Batch::find($this->batch_id),
'student_id' => Student::find($this->student_id), */
'subject' => $this->subject,
'marks' => $this->marks,
'marksgrade' => $this->marksgrade,
'total' => $this->total,
'grade' => $this->grade,
'percentage' => $this->percentage,
'year' => $this->year,
],
];
}
what I want is this
data": [
{
"exam_type": "Unit Test 1",
"details": {
//subject1 details
},
{
//subject2 details
},
{
//subject3 details
},
"exam_type": "Unit Test 2",
"details": {
//subject1 details
},
{
//subject2 details
},
{
//subject3 details
},
},
what I am getting for the above code
"data": [
{
"exam_type": "Unit Test 1",
"details": {
//subject1 marks details
}
},
{
"exam_type": "Unit Test 1",
"details": {
//subject2 marks details
}
},
Here is something you can try:
First get exam types
$exam_types = StudentsMark::select('exam_type', 'student_id', 'academic_id')->whereIn('academic_id',$ids)->whereIn('student_id',$studentid)->get();
$marks = StudentMarksResource::collection($exam_types);
Now inside resource that's when you can retrieve the details
#do not forget to import StudentsMark
#and you can make a resource for details, just to make clean code
return [
'exam_type' => $this->exam_type,
'details' => StudentsMark::where('academic_id', $this->academic_id)
->where('student_id', $this->student_id)
->get();
];

How to remove objoct from object by finding in type script

This is my object
"filterValue":[
{"label":"--Select a Member--","value":""},
{"label":"ghi.jkl","value":{"Id":"1",}},
{"label":"abc.def","value":{"Id":"2",}},
{"label":"asd.vdf","value":{"Id":"3",}},
]
from this i want to search where value.Id = 2 and i want to remove that obeject line.
how can i do that..?
note:first value will be empty there is no data in value.
i have tried something like this:
filterValue.splice( filterValue.indexOf(2), 1 );
You can't use indexOf in this case because you are checking a complex object but you can use findIndex like this:
filterValue.splice( filterValue.findIndex(a => a.Id == 2), 1 );
You might want to change the code the check if findIndex actually found something by checking if it returns something larger than (or equal to) 0.
You can use filter to get a new filtered array (filteredArr):
var arr = [
{"label":"--Select a Member--","value":""},
{"label":"ghi.jkl","value":{"Id":"1",}},
{"label":"abc.def","value":{"Id":"2",}},
{"label":"asd.vdf","value":{"Id":"3",}}
];
var filteredArr = arr.filter((x) => JSON.stringify(x.value) !== JSON.stringify({"Id":"2"}));
console.log(filteredArr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You have a couple of subtly traps to avoid with your specific example.
The structure of items differs, so you need to be careful that you don't have a problem with the "--Select a Member--" item, which doesn't have a value.Id.
The example below cheaply solves the type issue (the best common type between the array members doesn't contain the property you are interested in).
const items = [
{ "label": "--Select a Member--", "value": "" },
{ "label": "ghi.jkl", "value": { "Id": "1", } },
{ "label": "abc.def", "value": { "Id": "2", } },
{ "label": "asd.vdf", "value": { "Id": "3", } },
];
const filtered = items.filter((i: any) => !i.value || !i.value.Id || i.value.Id !== '2');
console.log(filtered);
Output:
[
{"label":"--Select a Member--","value":""},
{"label":"ghi.jkl","value":{"Id":"1"}},
{"label":"asd.vdf","value":{"Id":"3"}}
]
const obj = {
filterValue: [
{ label: "--Select a Member--", value: "" },
{ label: "ghi.jkl", value: { Id: "1" } },
{ label: "abc.def", value: { Id: "2" } },
{ label: "asd.vdf", value: { Id: "3" } }
]
};
var changedObj = obj.filterValue.filter((data, index) => {
return data.value.Id != "1";
});
console.log(changedObj);

Laravel Array & JSON Casting to Algolia

I am trying to send some data along to Algolia through the toSearchableArray. Any strings I have stored in my DB are sending along fine, but I hit a roadblock when trying to push nested JSON data along—the information is being sent as a string with characters escaped.
This is a sample of the nested object that I am storing in my table (MySQL with a JSON data type):
[
{
"id": 19,
"name": "Mathematics",
"short": "Math"
},
{
"id": 23,
"name": "Science",
"short": "Science"
},
{
"id": 14,
"name": "Health and Life Skills",
"short": "Health"
}
]
My model looks like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Resource extends Model
{
use Searchable;
protected $primaryKey = 'objectID';
public function toSearchableArray()
{
$data = $this->toArray();
$data['grades'] = explode(';', $data['grades']);
$data['units'] = explode(';', $data['units']);
return $data;
}
}
I get an output that looks like this:
array:22 [
"objectID" => 1
"name" => "Resource #1"
"slug" => "resource-1"
"write_up" => """
This is an example write up.
"""
"author" => "johnny"
"type_name" => "Lesson Plan"
"language" => "English"
"grades" => array:3 [
0 => "Kindergarten"
1 => "Grade 1"
2 => "Grade 4"
]
"subjects" => "[{"id": 19, "name": "Mathematics", "short": "Math"}, {"id": 23, "name": "Science", "short": "Science"}, {"id": 14, "name": "Health and Life Skills", "short": "Health"}]"
"units" => array:2 [
0 => "Unit A"
1 => "Unit B"
]
"main_image" => "https://dummyimage.com/250x325/000000/fff.png&text=Just+a+Test"
"loves" => 88
"downloads" => 280
"created_at" => "2018-01-01 13:26:47"
"updated_at" => "2018-01-02 10:10:32"
]
As you can see, the 'subjects' attribute is being stored as a string. I know there is attribute casting in 5.5 (I am running 5.5), but I am not too clear on how I would implement the example they have for Array & JSON Casting in my work above. https://laravel.com/docs/5.5/eloquent-mutators#attribute-casting
Would anyone be willing to show me an example?
I'd rely on Attribute Casting for this, add a $casts property in your model and it will be done automatically.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Resource extends Model
{
use Searchable;
protected $primaryKey = 'objectID';
protected $casts = [
'subjects' => 'array',
];
public function toSearchableArray()
{
// Same function as you posted
}
}
You can also do it manually in your toSearchableArray method with $data['subjects'] = json_decode($this->subjects, true);
I answered with more details on this other posts: https://discourse.algolia.com/t/laravel-array-json-casting-to-algolia/4125/2

Representing logic as data in JSON

For business reasons we need to externalize some conditional logic into external files: preferably JSON.
A simple filter-by scenario could be handled by adding a node as follows:
"filter": [
{
"criteria": "status",
"value": "open",
"condition": "=="
}
]
Multiple conditions could be handled by additional values in the array.
"filter": [
{
"criteria": "status",
"value": "open",
"condition": "=="
},
{
"criteria": "condition2",
"value": "value2",
"condition": "=="
}
]
However, it gets a little confusing when we have handle complex conditions involving ANDs or ORs.
Question: is there a standardized (or even widely accepted) format for representing such logic within JSONs? How would you do it if it were up to you?
NOTE: The first answer has been made an editable wiki so it can be improved by anyone who feels it can be.
If you must implement this using standard JSON, i'd recommend something akin to Lisp's "S-expressions". A condition could be either a plain object, or an array whose first entry is the logical operation that joins them.
For example:
["AND",
{"var1" : "value1"},
["OR",
{ "var2" : "value2" },
{ "var3" : "value3" }
]
]
would represent var1 == value1 AND (var2 == value2 OR var3 == value3).
If you prefer brevity over consistency, you could also allow an object to have multiple properties, which would implicitly be joined by an AND. For example, { "a": "b", "c": "d" } would be equivalent to ["AND", { "a": "b" }, { "c": "d" }]. But there are cases (like the example) where the former syntax can not faithfully represent the condition as written; you'd need additional trickery like translating the condition or using dummy property names. The latter syntax should always work.
I needed a format that would:
Support comparisons other than equality.
Let variables appear in any position, not just be compared to literals.
Be consistent, terse, secure, and extensible.
So I built up a format I'm calling JsonLogic. A rule is a JSON object, with the operator in the key position, and one or an array of arguments in the value position. (Inspired by Amazon CloudFormation functions.) Any argument can be another rule, so you can build arbitrarily deep logic.
I've also written two parsers for it: JsonLogic for JavaScript and JsonLogic for PHP.
cHao's example would be written as
{ "and", [
{"==", [ {"var" : "var1"}, "value1" ]},
{ "or", [
{"==", [ {"var" : "var2"}, "value2" ]},
{"==", [ {"var" : "var3"}, "value3" ]}
]}
]}
var here is the operator to get a property of the "data" object, passed along with the "rule" object to the parser, e.g.:
jsonLogic(
{"==", [{"var":"filling"}, "apple"]} // rule, is this pie apple?
{"filling":"apple", "temperature":100} // data, a pie I'm inspecting
);
// true
There are lots more possible operators (greater than, not-equals, in-array, ternary, etc) and both parsers are available on GitHub (with unit tests and documentation).
By the way, IBM DB2 supports logic statements encoded in JSON.
Boolean operations look like a cross between cHao's solution and Amazon CloudFormation:
{"$and":[{"age":5},{"name":"Joe"}]}
Comparison operations look, to me, like transliterated SQL. (Instead of Amazon or Russellg or cHao's movement toward an abstract syntax tree.)
{"age":{"$lt":3}}
I had a similar need (to build up a sql where clause in javascript). I create dthe following javascript function:
function parseQuery(queryOperation){
var query="";
if (queryOperation.operator == 'and')
query = "(" + parseQuery(queryOperation.leftOp) + ") AND (" + parseQuery(queryOperation.rightOp) + ")";
if (queryOperation.operator == 'or')
query = "(" + parseQuery(queryOperation.leftOp) + ") OR (" + parseQuery(queryOperation.rightOp) + ")";
if (queryOperation.operator == '=')
query = "(" + queryOperation.leftOp +" = "+ queryOperation.rightOp + ")";
return query;
}
I create my queryOperation Like this:
var queryObject = {
operator: 'and',
leftOp: {
leftOp: 'tradedate',
operator: '=',
rightOp: new Date()
},
rightOp: {
operator: 'or',
leftOp: {
leftOp: 'systemid',
operator: '=',
rightOp: 9
},
rightOp: {
leftOp: 'systemid',
operator: '=',
rightOp:10
}
}
};
When I pass my queryOperation to ParseQuery it returns
((tradedate= Thu Jul 24 17:30:37 EDT 2014)) AND (((systemid= 9)) OR ((systemid= 10)))
I need to add some type conversions and other operators, but the basic structure works.
I came up with this format with the primary goal of reading as close as possible to actually SQL.
Here's the Type def in typescript:
type LogicalOperator = 'AND' | 'OR';
type Operator = '=' | '<=' | '>=' | '>' | '<' | 'LIKE' | 'IN' | 'NOT IN';
type ConditionParams = {field: string, opp: Operator, val: string | number | boolean};
type Conditions = ConditionParams | LogicalOperator | ConditionsList;
interface ConditionsList extends Array<Conditions> { }
Or BNF (ish? my cs teachers wouldn't be proud)
WHEREGROUP: = [ CONDITION | ('AND'|'OR') | WHEREGROUP ]
CONDITION: = {field, opp, val}
With the following Parsing Rules:
AND is optional (I typically add it for readability). If logical LogicalOperator is left out between conditions, it will automatically joins them with AND
Inner arrays are parsed as nested groups (EG get wrapped in ())
this type does not restrict multiple logical operators consecutively (unfortunately). I handled this by just using the last one, although I could have thrown a runtime error instead.
Here are some examples (typescript playground link):
1 AND 2 (AND inferred)
[
{ field: 'name', opp: '=', val: '123' },
{ field: 'otherfield', opp: '>=', val: 123 }
]
1 OR 2
[
{ field: 'name', opp: '=', val: '123' },
'OR',
{ field: 'annualRevenue', opp: '>=', val: 123 }
]
(1 OR 2) AND (3 OR 4)
[
[
{ field: 'name', opp: '=', val: '123' },
'OR',
{ field: 'name', opp: '=', val: '456' }
],
'AND',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
]
1 AND (2 OR 3)
[
{ field: 'name', opp: '=', val: '123' },
'AND',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
]
1 AND 2 OR 3
[
{ field: 'name', opp: '=', val: '123' },
'AND',
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
1 OR (2 AND (3 OR 4))
[
{ field: 'name', opp: '=', val: '123' },
'OR',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'AND',
[
{ field: 'active', opp: '=', val: true },
'OR',
{ field: 'accountSource', opp: '=', val: 'web' }
]
]
]
As you can see, if you were to remove , and property names, then just replace the [] with (), you'd basically have the condition in SQL format
My colleague suggested this possible solution:
"all OR conditions would be an array while AND conditions would be objects,
For example,OR can match any of the objects in the array:
[
{
"var1":"value1"
},
{
"var2":"value2"
},
{
"var3":"value3"
}
]
AND would be
{
"var1":"val1",
"var2":"val2",
"var3":"val3"
}
Please check out (JSL)[https://www.npmjs.com/package/lib-jsl ].
It seems to fit the description given.
Here is a sample :
var JSL = require('lib-jsl');
var bugs = [
[{ bug : { desc: 'this is bug1 open', status : 'open' } }],
[{ bug : { desc: 'this is bug2 resolved', status : 'resolved' } }],
[{ bug : { desc: 'this is bug3 closed' , status : 'closed' } }],
[{ bug : { desc: 'this is bug4 open', status : 'open' } }],
[{ bug : { desc: 'this is bug5 resolved', status : 'resolved' } }],
[{ bug : { desc: 'this is bug6 open', status : 'open' } }],
[ { workInProgress : '$bug'},
{ bug : '$bug'},
{ $or : [
{ $bind : [ '$bug', { status : 'open'} ] },
{ $bind : [ '$bug', { status : 'resolved'} ] }
] }
]
];
var query = [{workInProgress : '$wip'}]
var transform = '$wip'
var jsl = new JSL ({
rules : bugs,
query : query,
transform : transform
});
var retval = jsl.run();
console.log(JSON.stringify(retval, null,2));
The response is :
[
{
"desc": "this is bug1 open",
"status": "open"
},
{
"desc": "this is bug2 resolved",
"status": "resolved"
},
{
"desc": "this is bug4 open",
"status": "open"
},
{
"desc": "this is bug5 resolved",
"status": "resolved"
},
{
"desc": "this is bug6 open",
"status": "open"
}
]
The main work is done by the query defined in the rule workInProgress :
[ { workInProgress : '$bug'},
{ bug : '$bug'},
{ $or : [
{ $bind : [ '$bug', { status : 'open'} ] },
{ $bind : [ '$bug', { status : 'resolved'} ] }
] }
]
This rule can be read as :
To satisfy the query with workInProgress, we define a variable {workInProgress : '$bug'}, which we then proceed to match against all bugs in the database using the next part of the rule {bug : '$bug'}. This part matches all bugs since the shape of the object (it's keys: 'bug') matches the bug records in the database. The rule further asks the $bug variable to be $bind(ed) against patterns containing relevant status values (open and closed) within a $or. Only those bug records whose status value in $bug satisfies all parts of the rule's body qualify for the result.
The result is finally transformed using the transform specification : transform : '$wip' which literally asks for an array of all values returned in the $wip variable of the query.
Following Jeremy Wadhams comment, I implemented a parser I hope it can help you:
https://play.golang.org/p/QV0FQLrTlyo
The idea is to set all logic operators in special keys with $ character like $and or $lte.
As an example:
{
"$or":[
{
"age":{
"$lte":3
}
},
{
"name":"Joe"
},
{
"$and":[
{
"age":5
},
{
"age ":{
" $nin ":[
1,
2,
3
]
}
}
]
}
]
}
Regards.
Is translated as:
( age <= 3 OR name = Joe OR ( age = 5 AND age NOT IN (1,2,3) ) )
Formula parser + a bit of JS codes to put data into formulas, is another solution described with example in this answer.
We created an npm package json-conditions to handle this. It's not as full featured as some of the others here, but it's easy to translate into a simple UI for non-technically savvy clients as complex rules are possible without nesting and it covers virtually all use cases they can come up with.
Example on runkit
const objectToTest = {
toy: {
engines: 1,
},
batteries: 'AA',
fun: true,
};
const simpleRules = [
// required: true means This first condition must always be satisfied
{ property: 'fun', op: 'eq', value: true, required: true },
{ property: 'toy.engines', op: 'gt', value: 2 },
{ property: 'batteries', op: 'present' },
];
// Returns true
checkConditions({
rules: simpleRules,
satisfy: 'ANY', // or ALL to require all conditions to pass
log: console.log,
}, objectToTest);
Following Jeremy Wadhams comment, I mapped the json by MongoDB logical query operator and MongoDB comparison query operator but MongoDB don't allow $ character in content:
{"and":[
{"age":{"eq": 5}},
{"name":{"eq": "Joe"}
]}
I just wanted to help by defining a parsing logic in JavaScript for the JSON structure mentioned in the answer: https://stackoverflow.com/a/53215240/6908656
This would be helpful for people having a tough time in writing a parsing logic for this.
evaluateBooleanArray = (arr, evaluated = true) => {
if (arr.length === 0) return evaluated;
else if (typeof arr[0] === "object" && !Array.isArray(arr[0])) {
let newEvaluated = checkForCondition(arr[0]);
return evaluateBooleanArray(arr.splice(1), newEvaluated);
} else if (typeof arr[0] === "string" && arr[0].toLowerCase() === "or") {
return evaluated || evaluateBooleanArray(arr.splice(1), evaluated);
} else if (typeof arr[0] === "string" && arr[0].toLowerCase() === "and") {
return evaluated && evaluateBooleanArray(arr.splice(1), evaluated);
} else if (Array.isArray(arr[0])) {
let arrToValuate = [].concat(arr[0]);
return evaluateBooleanArray(
arr.splice(1),
evaluateBooleanArray(arrToValuate, evaluated)
);
} else {
throw new Error("Invalid Expression in Conditions");
}
};
So the param arr here would be an array of conditions defined in the format as described by the attached link.
The first came to mind would be the recurisve
dict1={'$lte':'<','$nin':'not in '}
def updateOp(subdictItem):
for ites in subdictItem:
ops = ites
print dict1.get(ops), subdictItem.get(ops), type(subdictItem.get(ops))
if type(subdictItem.get(ops)) is list:
valuelist=subdictItem.get(ops)
strlist=' ,'.join([str(x) for x in valuelist])
sub = dict1.get(ops) + "(" +strlist +")"
else:
sub = dict1.get(ops) +' ' + str(subdictItem.get(ops))
return sub
def jsonString(input_dict):
items=''
itemslist=[]
list = []
for item in input_dict:
op=item
itemssublist=[]
# print "item",op
for subitem in input_dict.get(op):
# print("subitem",subitem)
for ite in subitem:
if ite not in ('and','or'):
# print('ite_raw',ite,subitem.get(ite))
sub=''
if type(subitem.get(ite)) is dict:
sub=updateOp(subitem.get(ite))
else:
sub='=' + str(subitem.get(ite))
itemssublist.append(ite+sub)
else:
item1=jsonString(subitem)
itemssublist.append(item1)
delimiter=" "+op+ " "
items= "("+delimiter.join(itemssublist)+")"
return items
if __name__ == "__main__":
input_dict={}
with open('ops.json','r') as f:
input_dict=json.load(f)
print input_dict
test= jsonString(input_dict)
#result : (age< 3 or name=Joe or (age=5 and age not in (1 ,2 ,3)))
ops.json file:
{
"or":[
{
"age":{
"$lte":3
}
},
{
"name":"Joe"
},
{
"and":[
{
"age":5
},
{
"age ":{
"$nin":[
1,
2,
3
]
}
}
]
}
]
}
Logic can be implemented with "logicOp": "Operator" on a "set": ["a","b" ...]
For cHau's example:
"var": {
"logicOp": "And",
"set": ["value1",
{
"LogicOp": "Or",
"set": ["value2", "value3"]
}
]
}
There can also be other attributes/operations for the set for example
"val": { "operators": ["min": 0, "max": 2], "set": ["a", "b", "c"] }
For a sundae with two scoops of one or more icecream types, 1 toppings and whipcream
"sundae": {
"icecream": {
"operators": [ "num": 2,
"multipleOfSingleItem": "true"],
"set": ["chocolate", "strawberry", "vanilla"]
},
"topping": {
"operators": ["num": 1],
"set": ["fudge", "caramel"]
},
"whipcream": "true"
}
Use arrays, alternate between OR and AND conditions:
const rule0 = [
[ "ruleA1", "ruleA2", "ruleA3" ],
[ "ruleB5", "ruleB6" ],
[ "ruleB7" ]
];
const rule1 = [
[ "ruleA1", "ruleA2", [ [ "ruleA3A" ], [ "ruleA3B1", "ruleA31B2" ] ] ],
[ "ruleB5", "ruleB6" ],
[ "ruleC7" ]
];
function ruler (rules) {
return "( " +
rules.map(or_rule =>
"( " +
or_rule.map(and_rule =>
Array.isArray(and_rule) ? ruler(and_rule) : and_rule
).join(" AND ") +
" )"
).join(" OR ") + " )";
}
Output:
ruler(rule0)
'( ( ruleA1 AND ruleA2 AND ruleA3 ) OR ( ruleB5 AND ruleB6 ) OR ( ruleB7 ) )'
ruler(rule1)
'( ( ruleA1 AND ruleA2 AND ( ( ruleA3A ) OR ( ruleA3B1 AND ruleA31B2 ) ) ) OR ( ruleB5 AND ruleB6 ) OR ( ruleC7 ) )'
I created a structure thinking about a sequential iteration:
[
{
"operator": null,
"field": "age",
"condition": "eq",
"value": 5
},
{
"operator": "and",
"field": "name",
"condition": "eq",
"value": "Joe"
}
]
Want to throw my own hat in the ring here.
The best serializable predicate you can use to represent logic in JSON format has already largely won the day. It’s called JSON Schema (yes, a schema is a predicate, data will either validate against it or it won’t - true/false - a predicate)
Why do I say it’s win the day? We use it everywhere all the time, open API/swagger, embedded in our IDEs autocompletes, in various dev documentation websites
All you have to do is wrap some logic around how to resolve your data and feed it to a json schema validator with a json schema
https://www.npmjs.com/package/json-schema-rules-engine