Iterate connected nodes in cytoscape.js - cytoscape.js

I need to get the nodes connected to a given node, and highlight them. The "components" function looks good for this, however my traversal fails. The component collection shows a size of one and only the original node gets highlighted.
cynode = cy.getElementById(idstr);
comps = cynode.components();
for (i = 0; i < comps.length; i++) /* really there's only one component */
{
comp = comps[i];
alert(comp.size()); /* this always returns 1!! */
comp.nodes().addClass('nodehlt'); /* only the original node gets highlighted */
}

From the docs:
eles.components() : Get the connected components, considering only the elements in the calling collection. An array of collections is returned, with each collection representing a component.
If the set of elements you consider is only a single node, there can only ever be one component.
You need to get the components of the whole graph (cy.elements.components()) -- or of the subgraph you're interested in. Of those components, you then need to find the one that contains the node of interest.

Related

Terraform list element out of bounds?

From the Terraform docs:
element(list, index) - Returns a single element from a list at the given index. If the index is greater than the number of elements, this function will wrap using a standard mod algorithm.
What would be a good reason to wrap using mod? This behavior seems to me like it could be the cause of lots of headaches.
At the top of my head I can only remember two other approaches to handle accessing an element that's out of bounds:
Python/Ruby: return None/Nil
Java/JS/Ruby: Raise an error
I'm so used to them that they seem to make sense, you either get nothing or an error but why would you ever expect to get the k mod n element in the list? If you were the implementer, how would you justify this choice of behavior.
It's a shortcut for having to do the mod yourself but can be useful when looping over a short list such as the amount of subnets or availability zones that you want to put multiple instances in.
This is a pretty common pattern and appears in the aws_subnet_ids data source docs:
data "aws_subnet_ids" "private" {
vpc_id = "${var.vpc_id}"
tags {
Tier = "Private"
}
}
resource "aws_instance" "app" {
count = 6
ami = "${var.ami}"
instance_type = "t2.micro"
subnet_id = "${element(data.aws_subnet_ids.private.ids, count.index)}"
}
If you were to use the slice operator instead you would get an index out of bounds exception as soon as you have more instances than subnets returned by the data source.

Get array of data based on hierarchical edges sequence in cytoscape.js

I use cytoscape.js to organize an flow of nodes that represent an tasks execution. Sometimes an task is not created hierarchicly.
At least in a visual way, edges gives the correct sequence.
I would like to get the hierarchical sequence based on the edges and list their data as an array. Each index will be dispposed as edges says so.
The image above represent a sequence based on the edges arrows. I would like to transform this edges/arrows sequence into a perfect sequence of data (array).
The cytoscape.elements().toArray() method transform visual to array, but it is delivered the same sequence of the original data.
How can it be done? Is there some method in cytoscape core?
The easiest way would be to give the nodes id's with the corresponding numbers in your sequence:
-> The first task to execute has the id 1, the second has the id 2...
After initialization you can then do a loop with n iterations (n = number of nodes in cy) and get the nodes one by one. That way you can access their information and enter this data into an array:
for (i = 0; i < cy.nodes().length; i++) {
var curr = cy.nodes("[id = '" + i + "']"); // This way you get the node with the id == i
//do stuff
array[i] = theDataYouNeed;
}
If you want the nodes to be in a hierarchy, you would have to rethink your layout. An hierarchy in cytoscape can be achieved by "directed acyclic graph" (= dagre in cytoscape).

How do I speed up 'watching' multiple arrays with the same data in vue.js

A large amount of data (+-15 000 records) is loaded via AJAX which is then used to populate two arrays, one sorted by ID the other by a name. Both the arrays contains the same objects just ordered differently.
The data is displayed in a tree view but the hierarchy can be changed by the user. The tree is virtualised on the first level so only the records displayed + 50% is 'materialized' as vue components.
Supplying both of the arrays as data to a vue instance is very slow. I suspect vue.js is adding observers to the objects twice, or change notifications is sent multiple times, I don't really know.
So only one of the arrays is added to vue the other is used out of band.
Vue slows down the addition of elements to an array a lot. If the array is populated before it is bound to the vue instance it takes +-20s before the tree view is displayed. If I bind it before populating the arrays it takes about +-50s before the tree view becomes usable (the elements are displayed almost instantly). This could be because of notifications going for all these elements added.
Is there a way to add a second array with duplicate data so vue.js watches it for changes, but it doesn't slow vue down as much?
Is there a way to switch watching/notifications of temporarily so elements could be added to an array without the penalty, yet be 'watched' when notifications is switched back on?
I'm not sure that my reasoning behind the slowdowns is correct, so maybe my questions are misguided.
O another thing I need the arrays to be watched and only one of the properties of the elements.
var recordsById = [];
var recordsByName = [];
// addRecord gets called for every record AJAX returns, so +-15 000
// calling addRecord 15 000 times before 'binding' takes 20 sec (20 sec with no display)
// calling addRecord after 'binding' takes > 50 sec (instant display but CPU usage makes treeview unausable)
function addRecord(record) {
var pos = binarySearch(recordsById, record);
recordsById.splice(0, pos, record);
pos = binarySearch(recordsByName, record);
recordsByName.splice(0, pos, record);
}
var treeView = new Vue({
el: '#treeView',
data: {
// If I uncomment following line, vue becomes very slow, not just for initial loading, but as a whole
//recordsById: recordsById,
recordsByName: recordsByName
},
computed: {
virtualizedList: function() {.....}
}
})
There are a couple techniques which might improve your performance.
Using the keys
For rendering large lists, the first thing you want to do is use a key. A great candidate for this is the id you speak about.
Use pagination
An obvious solution to "displaying a lot of data is slow" is "display less data". Let's face it, 15 000 is a lot. Even if Vue itself could insert and update so many rows quickly, think of the user's browser: will it be able to keep up? Even if it was the simplest possible list of text nodes, it would still be a lot of nodes.
Use virtual scrolling technique
If you don't like the look of pagination, a more advanced approach would be virtual scrolling. As user browses this large list, dynamically add the elements below, and remove the ones that the user has already seen. You keep the total number of elements from the list at the DOM at once to minimum.

Leaflet : Dynamically count number of feaures loaded into a layer

I have an application where markers/features are loading into layers/layerGroups (what's the right term?) from multiple sources, and they're loading dynamically (based on some attribute in feature.properties and other conditions). I want to be able to tell on the sidepanel the number of markers currently loaded into the layer on display. Given just the layer's variable/identifier, how can one find the number of markers/features loaded into it?
var layer1= L.layerGroup();
layerControl.addOverlay(layer1, 'Layer 1');
... // loading stuff into this layer from different sources
console.log(layer1.length); // doesn't work, gives "undefined"
console.log(JSON.stringify(layer1)); // doesn't work, "TypeError: cyclic object value"
..so I guess layers can't be treated like JSON objects.
I found a related question, but the answer there only addresses markers loaded from one geoJson source and advises a simple counter++ in the onEachFeature. I'm working with a lot of layers in my application and would appreciate not having to put a separate counter variable for each and every one, rather want to just use the layer's variable/identifier to count. If we can add a layer to a map or clustergroup so simply then we ought to be able to count what's in it, right?
The getLayers() function returns an array containing all the features in your object. Then you can get the length of that array.
layer_variable.getLayers().length;

How do I find the middle element of an ArrayList?

How do I find the middle element of an ArrayList? What if the size is even or odd?
It turns out that a proper ArrayList object (in Java) maintains its size as a property of the object, so a call to arrayList.size() just accesses an internal integer. Easy.
/**
* Returns the number of elements in this list.
*
* #return the number of elements in this list
*/
public int size() {
return size;
}
It is both the shortest (in terms of characters) and fastest (in terms of execution speed) method available.
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.0size
So, presuming you want the "middle" element (i.e. item 3 in a list of 5 items -- 2 items on either side), it'd be this:
Object item = arrayList.get((arrayList.size()/2)+1);
Now, it gets a little trickier if you are thinking about an even sized array, because an exact middle doesn't exist. In an array of 4 elements, you have one item on one side, and two on the other.
If you accept that the "middle" will be biased to ward the end of the array, the above logic also works. Otherwise, you'll have to detect when the size of the elements is even and behave accordingly. Wind up your propeller beanie friends...
Object item = arrayList.get((arrayList.size()/2) + (arrayList.size() % 2));
if the arraylist is odd : list.get(list.size() / 2);
if the arratlist is even: list.get((list.size() / 2) -1);
If you have a limitation for not using arraylist.size() / arraylist.length() method; you can use two iterators. One of them iterates from beginning to the end of the array, the other iterates from end to the beginning. When they reach the same index on the arraylist, then you find the middle element.
Some additional controls might be necessary to assure iterators wait each other before next iteration, you should not miss the meeting point..etc.
While iterating, for both iterators you keep total number of elements they read. So they should iterate one element in a cycle. With cycle, I mean a process including these operations:
iteratorA reads one element from the beginning
iteratorB reads one element from the end
The iterators might need to read more than one index to read an element. In other words you should skip one element in one cycle, not one index.