Related
I created this graph and am trying to make it wieghted directed graph
class Graph{
#nodes;
constructor(){
this.#nodes={}
}
addNode(node){
this.#nodes[node]=[]
}
addEdge(source,vertix){
if( ! this.#nodes[source] || ! this.#nodes[vertix]){
return false
}
// this.vertix[destination]=distancex
if(! this.#nodes[source].includes(vertix)){
this.#nodes[source].push(vertix)
}
}
showNodes(){
console.log(this.#nodes)
}
}
and now am trying to add edges :
for(let i=0;i<citiesnamesarr.length;i++)
{
mapgraph.addNode(citiesnamesarr[i])
var x={}
var citiesform=document.getElementsByClassName(`check${citiesnamesarr[i]} `)
var distanceform=document.getElementsByClassName(`distance${citiesnamesarr[i]} `)
for(let j=0;j<citiesform.length;j++)
{
var edge=citiesform[j].value
var distance=distanceform[j].value
x[edge]=distance
}
v[i]=x
mapgraph.addEdge(citiesnamesarr[i],v[i])
}
but when I print the graph it gives me an empty array :
{city1: Array(0), city2: Array(0), city3: Array(0)}
knowing when I tried to print the array v it works
0:{city2: '87', city1: ''}
1: {city0: '12', city1: '78'}
2: {city0: '', city1: '21'}
The main problem in what you're doing is that your method addEdge is meant to add one edge at the time, but when you're calling it in your code, you're trying to add multiple edges at the same time.
I rewrote your code for better understanding:
for(let cityname of citiesnamesarr){
mapgraph.addNode(cityname);
var adjacentVertices={};
var cityInputArr=document.getElementsByClassName(`check${cityName} `);
var distanceInputArr=document.getElementsByClassName(`distance${cityName} `);
for(let key in cityInputArr){
var destination=cityInputArr[key].value;
var distance=distanceInputArr[key].value;
adjacentVertices[destination]=distance;
}
mapgraph.addEdge(cityname,adjacentVertices);
}
To solve the issues, you'd either need to call your method addEdges and do something like:
addEdges(node,edges){
this.#nodes[node] = edges;
}
And call this method instead.
Or you can keep a method that adds a single edge with:
addEdge(source, destination, distance){
this.#nodes[source].push([destination, distance]);
}
And change your code to something like:
for(let cityname of citiesnamesarr){
mapgraph.addNode(cityname);
var cityInputArr=document.getElementsByClassName(`check${cityName} `);
var distanceInputArr=document.getElementsByClassName(`distance${cityName} `);
for(let key in cityInputArr){
var destination=cityInputArr[key].value;
var distance=distanceInputArr[key].value;
mapgraph.addEdge(cityname,destination, distance);
}
}
Note that a weighed graph has a more complex structure that an unweighed graph.
An unweighed graph can be represented as an adjacency list:
0: [1, 4, 6]
1: [0, 3, 4]
etc.
While for a weighed graph needs to store an additional value:
0: [[1, 300], [4, 250], [6, -20]]
1: [[0, 100], [3, 76], [4, -10]]
etc.
Depending on which algorithms you'd like to use, a matrix might be more convenient.
I am trying to incorporate chroma.js into my leaflet map so that i can toggle between quantiles, equal interval, and k-means, but the second and third argument for the domain function does not change anything
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
Here is the full code for the function
this.getRegionItemColor = function(item) {
var regionData = Mapbook.getRegionData();
var voterList = Mapbook.getColorScheme();
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
if (!_.isUndefined(item)) {
var voters = item.voters,
minVoters = regionData.min_voters,
maxVoters = regionData.max_voters;
var alpha = colorScale(voters);
return alpha;
}
else {
return 0;
}
}
Does anyone know why changing the number of buckets or classification method does not change anything?
Strange... I looked into it and I do think there is a problem with the library. Let's consider a very simple and documented example.
If you look at the documentation on github, here is what is written (https://github.com/gka/chroma.js/wiki/Color-Scales):
// Calling .domain() with no arguments will return the current domain.
chroma.scale(['white', 'red']).domain([0, 100], 4).domain() // [0, 25, 50, 75, 100]
When I do the same, however, this returns [0,100] (and not [0, 25, 50, 75, 100]); as you said, the second argument has not changed anything. You may want to flag that behavior as a bug on the plugin github page. Unless someone has a good explanation?
I was having the same problem, then I realized that at the time I defined 'ColorScale', my domain was not yet populated. are you certain that 'voterList' had your dataset in it at the time you defined ColorScale?
I'm using a JS Library called Javascript Clipper for polygon operation. As stated from the manual, the coordinate format of an input path is like the follows,
var paths = [[{X:30,Y:30},{X:130,Y:30},{X:130,Y:130},{X:30,Y:130}],
[{X:60,Y:60},{X:60,Y:100},{X:100,Y:100},{X:100,Y:60}]];
My question is, how to convert a regular JS array, say
var x = [40, 100, 1, 5, 25, 10] and var y= [22, 32, 11, 45, 75, 19] to the required format shown above? The actual case is, these coordinate points will not be typed manually, but obtained from another function, the output of which is not in the format required by the Javascript Clipper Library.
Something like this:
function makePath(xVals, yVals) {
var pathArray = [];
xVals.forEach(function(xVal, index) {
var yVal = yVals[index];
var coordObj = {xVal, yVal};
pathArray.push(coordObj);
})
return pathArray;
}
You can pass it your arrays, x and y, as makePath(x,y) to get the combined array out.
My method assumes that the lengths of the arrays x and y are the same.
So I have a bar chart with for example this array:
[12, 32, 42, 32, 43, 0, 0, 0, 5, 0, 0, 0]
So I have this array from markers from a google map with a length of 6, so from index 0 to 5.
I have an highlight event on the bar chart that when fired, it gives me the pointindex. I use the pointindex to get the marker from the google maps array, like: "gmap.markers[pointindex]". This works fine for the first 5 values from the bar chart array. but the ninth value from the bar chart array has the pointindex 8, but my google maps array only has 0 till 5 as index. So it doesn't work anymore. Basicly the pointindex 8 is basicly the index 5 from the google maps marker array.
This problem would also occur with as example these values.
Bar chart array: [12, 32, 42, 32, 43, 0, 7, 0, 5, 0, 0, 0]
Google map marker array with a length of 7, so index from 0 to 6.
I have this code for the highlight of a bar in the chart, this event is fired and I do stuff with the marker to highlight a marker(basically change the icon.
chart.bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
marker = gmap.markers[pointIndex];
if (marker !== null && marker !== undefined) {
marker.setIcon('https://maps.gstatic.com/mapfiles/ms2/micons/blue-dot.png');
}
}
);
As I explained when there is empty data in a pointindex of the bar chart array, the index of the bar doesn't match anymore with the index of the google marker.
I thought in my head to copy the bar chart array to a new array and remove all values that contain "0". and than compare the value from the bar chart array with the new array without "0" values's to see what the index is in the new array. So that it would match again with the google map marker index. But then you have the problem that if the bar chart array has 2 values that are the same, then this method doesn't work anymore.
Does anyone know a solution to this, in my head the problem is really simple, but I can't figure it out in code.
So #Nina's solution works in principle but not in terms of UI interaction.
Basically you need to see if the bar that was clicked has a value, and if it does, which index it maps to in Nina's filtering solution. Once you have the index that the value lies in from the filtered array, you can map that to your markers array.
To do this:
I think your best bet is, when building the bar chart to maintain an array with an object that is like { filteredIndex: N }. This array will be same length as the bar chart and tells you which index it maps to in the filtered array. If the data is 0, then the filteredIndex will be null.
You can do this simply by iterating your data and pushing the value to the filtered array if it's value is greater than 0, and maintaining the index, in a separate mapping array.
Thanks #Alex for the idea, and thanks #NinaScholz for the help, but I think you misunderstood my question, I know it was a vague question, sorry.
I have solved it by doing this.
when the page is loaded I do this:
var barArray = PF('dataChart').plot.data[0];
var mappingArray = new Array(barArray.length);
var j = 0;
for (var i = 0; i < barArray.length; i++) {
if (barArray[i] !== 0) {
mappingArray[i] = j;
j++;
} else {
mappingArray[i] = null;
}
}
And the listener now does this:
chart.bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
marker = gmap.markers[mappingArray[pointIndex]];
if (marker !== null && marker !== undefined) {
marker.setIcon('https://maps.gstatic.com/mapfiles/ms2/micons/blue-dot.png');
}
}
);
So basically I make a new array that is as long as the chart array, if the value from the chart array has a value that is not 0, I set the value of this index in the mappingArray to a counted up index, that matches with the google markers index. If this can be done better, please do tell!
Here is the solution with the preserved index and the right index for sparse access.
var barChart = [12, 32, 42, 32, 43, 0, 7, 0, 5, 0, 0, 0],
filtered = [];
barChart.forEach(function (a, i) {
a && filtered.push({ value: a, index: i });
});
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
So I'm making this small little application that allows users to enter a command to resize their div.
When doing this I want to make it easier by making a shorthand option that simply calls the same value from the full name, but this returns undefined.
Changing this.small to sizes.small returns the error:
Uncaught TypeError: Cannot read property 'small' of undefined
Here is my code:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight],
// Shorthand for sizes
s : this.small,
m : this.medium,
l : this.large,
f : this.fullscreen
}
// The following two calls should return the exact same result
console.log(sizes.small); // array[200, 150]
console.log(sizes.s); // undefined
Could anyone tell me what I'm doing wrong?
An object literal doesn’t change any contexts; it’s not a function. It’s more like an expression. sizes.small won’t work either, since although sizes is declared, it hasn’t been assigned a value at the time you’re reading it (which is to create the object that gives it a value).
You can assign the properties afterwards:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight]
};
// Shorthand for sizes
sizes.s = sizes.small;
sizes.m = sizes.medium;
sizes.l = sizes.large;
sizes.f = sizes.fullscreen;
make "s" be a function that returns "this.small"
That is,
var sizes = {
small : [200, 150],
s : function() {return this.small}
}
You can't reference properties that way. Here is one way to achieve what you want:
var sizes = new (function() {
this.small = [200, 150];
this.s = this.small;
})();
console.log(sizes.small);
console.log(sizes.s);
See on JSFiddle.
It is impossible to access other values in object before it is created.
You can try with:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight],
}
sizes.s = sizes.small;
sizes.m = sizes.medium;
sizes.l = sizes.large;
sizes.f = sizes.fullscreen;
In JavaScript
this
always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of. When we define, for example, a function in a page, its owner is the page, or rather, the window object (or global object) of JavaScript.