Problem setting edges in vis-network with typescript - vis.js

I'm following the Dynamic Dataset example from vis and I'm getting a typescript error when I try to set edges.
I just have an edge array that looks like:
edgesArray = [
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 3, to: 5 },
]
and I'm setting the data as
let data = {
nodes: new vis.DataSet(nodesArray),
edges: new vis.DataSet(edgesArray)
}
The error I'm getting is in the edges.
No overload matches this call.
Overload 1 of 2, '(options?: DataSetInitialOptions<"id">): DataSet<Partial<Record<"id", string | number>>, "id">', gave the following error.
Type '{ from: number; to: number; } []' has no properties in common with type 'DataSetInitialOptions<"id">'.
Overload 2 of 2, '(data: Partial<Record<"id", string | number>>[], options?: DataSetInitialOptions<"id">): DataSet<Partial<Record<"id", string | number>>, "id">', gave the following error.
Argument of type '{ from: number; to: number; } []' is not assignable to parameter of type 'Partial<Record<"id", string | number>>[]'.
I'm using version 5.2.4 of vis-network.

This is standard TS behavior. You're trying to assign type A into B but they have nothing in common. DataSet can accept items that have optional id. However your edges have no ids and TS simply says you're doing something wrong.
Solution one:
import { Edge } from "vis-network";
const edgesArray: Edge[] = [
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 3, to: 5 },
];
Solution two:
const edgesArray = [
{ id: undefined, from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 3, to: 5 },
];
Solution three:
const edgesArray: { id?: undefined, from: number, to: number }[] = [
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 3, to: 5 },
];

Related

Using mongolite in R to extract individual array items

I'm using mongolite in R to read a mongo collection with the following structure:
[{_id: 0, date: 20221201, dailyAnswer:[
{question:a,score:1},
{question:b,score:3},
{question:c,score:2}
]},
{_id: 1, date: 20221201, dailyAnswer:[
{question:a,score:3},
{question:b,score:2},
{question:c,score:1}
]},
{_id: 0, date: 20221202, dailyAnswer:[
{question:a,score:2},
{question:b,score:2},
{question:c,score:3}
]},
{_id: 1, date: 20221202, dailyAnswer:[
{question:a,score:3},
{question:b,score:1},
{question:c,score:1}
]}]
For each document I'd like to extract each question score into a column, with the table structure:
_id | date | question_a_score | question_b_score | question_c_score
In MongoDB Compass I've written a query to extract them:
{
q_a_score: { $arrayElemAt: [ "$dailyAnswer.score",0]},
q_b_score: { $arrayElemAt: [ "$dailyAnswer.score",1]},
q_c_score: { $arrayElemAt: [ "$dailyAnswer.score",2]}
}
Which returns:
[{
_id: 0,
question_a_score:1,
question_b_score:3,
question_c_score:2},
...,
{
_id: 1,
question_a_score:3,
question_b_score:1,
question_c_score:1}
}]
However, I'm not sure whether to use the $aggregate or $find methods in mongolite in R, and how to structure the pipeline or query arguments in those methods respectively.
Use the aggregate method with the $project and $arrayElemAt operators:
checkins_questions <- collection_connection$aggregate(pipeline = '[{"$project": {"dailyAnswerScore1": { "$arrayElemAt": [ "$dailyAnswer.score", 0 ] },
"dailyAnswerScore2": { "$arrayElemAt": [ "$dailyAnswer.score", 1 ] },
"dailyAnswerScore3": { "$arrayElemAt": [ "$dailyAnswer.score", 2 ] }}}]')

Using jq to conditionally flatten recursive json

The simplest version of the input document I could come up with is
{
"references": [
{
"version": 5,
"id": "id1",
"objType": "A"
},
{
"version": 4,
"id": "id2",
"objType": "B",
"referencing": []
},
{
"version": 4,
"id": "id3",
"objType": "B",
"referencing": [
{
"version": 2,
"id": "id4",
"objType": "A"
},
{
"version": 3,
"id": "id5",
"objType": "B",
"referencing": []
}
]
}
]
}
Objects of type A have no referencing objects.
Objects of type B can be referenced by either type of object.
There are two outputs I need from this json:
Output #1 is the version info for objects of type A with the id value as a key with the value of version. A objects can be at the top level or at some arbitrary depth in the referencing arrays.
{
"references": {
"id1": {"version": 5},
"id4": {"version": 2}
}
}
The 2nd output is similar: the version info for objects of type B. The can be a chain of type B objects referencing other type B objects.
{
"references": {
"id2": {"version": 4},
"id3": {"version": 4},
"id5": {"version": 3}
}
}
Use recursive decsent operator and from_entries. You don't need to follow the "references" (at least not to produce the expected output in your question)
{
dependencies: [.. | select(.objType=="A")? | { key: .id, value: {version} }] | from_entries
},
{
dependencies: [.. | select(.objType=="B")? | { key: .id, value: {version} }] | from_entries
}
Output:
{
"dependencies": {
"id1": {
"version": 5
},
"id4": {
"version": 2
}
}
}
{
"dependencies": {
"id2": {
"version": 4
},
"id3": {
"version": 4
},
"id5": {
"version": 3
}
}
}
It's also possible to merge (add) objects instead of constructing them from their entries, which makes the code minimally shorter:
{
dependencies: [.. | select(.objType=="A")? | { (.id): {version} }] | add
}
You can use recurse to traverse the document, INDEX to create an object with IDs as keys, map_values to format their values using select to reduce according to your criteria.
jq --arg type A '
.references |= (
INDEX(.[] | recurse(.referencing[]?); .id)
| map_values(select(.objType == $type) | {version})
)
'
{
"references": {
"id1": {
"version": 5
},
"id4": {
"version": 2
}
}
}
Demo
This works for both questions, provide A or B to --arg type.
Note that this is using the error suppression operator ? when recursing down. If you want to restrict the traversal explicitly to .objType == "B", just prepend it in a select expression, i.e. replace recurse(.referencing[]?) with recurse(select(.objType == "B") | .referencing[]). Demo

filter nest tree object by object id

I have a tree object like below:
let data = [
{
id: 1,
children: [
{
id: 1.1,
children: [
{
id: 1.2,
children: []
},
{
id: 1.22,
children: []
}
]
}
]
},
{
id: 2,
children: []
}
]
I want to filter out id equal a specific value. In this case, I want to filter out id equal 1.2.
The rusult I want is like below:
let data = [
{
id: 1,
children: [
{
id: 1.1,
children: [
{
id: 1.22,
children: []
}
]
}
]
},
{
id: 2,
children: []
}
]
I have search a few question about filter nest deep object, But still don't know how. I need to use recursion to solve this.
This is my way:
function handleDelete (data) {
return data.filter(t => {
if (t.children.length) {
handleDelete(t.children)
})
} else {
return t.id !== '1.2'
}
})
}
let result = handleDelete(data)
delete a node and its descendants
Here's an effective technique using flatMap and mutual recursion1 -
del accepts an array of nodes, t, a query, q, and calls del1 on each node with the query
del1 accepts a single node, t, a query, q, and calls del on a node's children
const del = (t, q) =>
t.flatMap(v => del1(v, q)) // <-- 1
const del1 = (t, q) =>
q == t.id
? []
: { ...t, children: del(t.children, q) } // <-- 2
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1.2")
console.log(result)
In the output, we see node.id 1.2 is removed -
[
{
"id": 1,
"children": [
{
"id": 1.1,
"children": [
{
"id": 1.22,
"children": []
}
]
}
]
},
{
"id": 2,
"children": []
}
]
preserving the descendants
In the program above, if a node.id matches our query, the node and all of its descendent children are removed. If we only want to delete the parent node and keep the children, we can make a single modification (!) to the program -
const del = (t, q) =>
t.flatMap(v => del1(v, q))
const del1 = (t, q) =>
q == t.id
? del(t.children, q) // <-- !
: { ...t, children: del(t.children, q) }
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1") // <-- delete node.id equal to "1"
console.log(result)
Notice how the children for 1 are still included in the output -
[
{
"id": 1.1,
"children": [
{
"id": 1.2,
"children": []
},
{
"id": 1.22,
"children": []
}
]
},
{
"id": 2,
"children": []
}
]
without mutual recursion
Mutual recursion isn't the only way to do it, but it's the only way to avoid a dynamic type check, such as the one below. In this final revision, we remove a parent and all of its children, as we did in the first program, but this del is implemented using a single recursive function -
const del = (t, q) =>
Array.isArray(t) // <-- array
? t.flatMap(v => del(v, q))
: Object(t) === t // <-- object
? q == t.id
? []
: { ...t, children: del(t.children, q) }
: t // <-- neither (noop)
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1.2")
console.log(result)
The output is the same as the first program, where 1.2 and all descendants are removed -
[
{
"id": 1,
"children": [
{
"id": 1.1,
"children": [
{
"id": 1.22,
"children": []
}
]
}
]
},
{
"id": 2,
"children": []
}
]
1. See this technique used on a different data set in this related Q&A.
2. All programs in this answer produce a new tree. The original input is not modified by del (or del1).

How to alias array elements in CosmosDB documents?

I have the following document,
{
"VehicleDetailId": 1,
"VehicleDetail": [
{
"Id": 1,
"Make": "BMW"
},
{
"Id": 1,
"Model": "ABDS"
},
{
"Id": 1,
"Trim": "5.6L/ASMD"
},
{
"Id": 1,
"Year": 2008
}
]
}
I want to give aliases for the array elements, something like this,
{
"VehicleDetailId": 1,
"Type": "VehicleDetail",
"VehicleDetail": [
{
"MakeId": 1,
"MakeValue": "BMW"
},
{
"ModelId": 1,
"ModelValue": "ABDS"
},
{
"TrimId": 1,
"TrimValue": "5.6L/ASMD"
},
{
"YearId": 1,
"YearValue": 2008
}
]
}
The following query seems to work fine, but since Id is common for all, it is repeating every time.
SELECT c.vehicleDetailId, ARRAY(SELECT v.Id AS MakeId, v.Make AS MakeValue,
v.Id AS ModelId, v.Model AS ModelValue,
v.Id AS TrimId, v.Trim AS TrimValue,
v.Id AS YearId, v.Year AS YearValue
FROM v IN c.VehicleDetail) AS VehicleDetail
FROM c
How should I write the query so that the Id does not repeat every time, and I can fetch an element from a specific position?
You could use UDF to implement your needs.
Udf code:
function userDefinedFunction(array){
var returnArray = [];
for(var i=0;i<array.length;i++){
var obj = array[i];
var map = {};
if(obj.Make){
map["MakeId"]= obj.Id;
map["MakeValue"]= obj.Make;
}else if(obj.Model){
map["ModelId"]= obj.Id;
map["ModelValue"]= obj.Model;
}else if(obj.Trim){
map["TrimId"]= obj.Id;
map["TrimValue"]= obj.Trim;
}else if(obj.Year){
map["YearId"]= obj.Id;
map["YearValue"]= obj.Year;
}
returnArray.push(map);
}
return returnArray;
}
Sql:
SELECT c.VehicleDetailId,udf.test(c.VehicleDetail) AS VehicleDetail
FROM c
Output:

Using a key within a map

I have this function:
def getMap(value = null) {
[
"SomeTitle": [ Param: 9, Size: 2, Default: 150, Val: value ]
]
}
and I can use getMap(152).SomeTitle.Val
What I want to do is use the key Size while calculating the Key Val, something like:
def getMap(value = null) {
[
"SomeTitle": [ Param: 9, Size: 2, Default: 150, Val: value * Size ]
]
}
Is there a way to use the Value of a Key within a map as a variable while calculating the Value of a another Key
This in Java/Groovy
Groovy can't autoreference the map on it's initialization, but you can use a with {} method to do some post-initialization processing:
def getMap(value = null) {
[
"SomeTitle": [ Param: 9, Size: 2, Default: 150 ].with {
put('Val', value * get('Size'))
it
}
]
}
assert getMap(10).SomeTitle.Val == 20

Resources