protovis magical properties - scope

I am pretty new to protovis. I was trying to understand the example in http://mbostock.github.com/protovis/docs/panel.html I can understand left(function() this.index * 10)is actually left(function(){return this.index * 10;}) and when the function is called a scope is passed to it thats this well and fine till now. BUt data(function(array) array) doesn't takes the array from this. rather its passed to it. from where this array is passed ? I cannot understand the flow of the chain.

This is one of the many parts of Protovis that's a bit confusing at first. When you add data to a mark, e.g.:
var mark = new pv.Panel()
.data([1,2,3]);
the mark will be duplicated once for each item in the data array, and passed the corresponding item as the first argument to its functions, e.g.:
new pv.Panel()
.data([1,2,3])
.title(function(d) { // <-- d is 1, 2, or 3
return d;
});
Any child mark you attach to mark will also receive this data point, which can then be used by the child mark as the input argument for its functions, e.g.:
new pv.Panel()
.data([1,2,3])
.add(pv.Label)
.text(function(d) { // <-- d is 1, 2, or 3
return d;
});
But child marks can also define their own data(), which will duplicate that mark accordingly. A child mark's data can be totally independent, e.g.:
new pv.Panel()
.data([1,2,3])
.add(pv.Label)
.data([3,4,5])
.text(function(d) { // <-- d is 3, 4, or 5
return d;
});
But often, as in the example you link to, the parent will have a 2- or 3-d array as its data, and the child will base its data() on the sub-array it's passed:
new pv.Panel()
.data([[1,2,3], [3,4,5]])
.add(pv.Label)
.data(function(d) { // <-- d is [1,2,3] or [3,4,5]
return d;
})
.text(function(d) { // <-- d is either 1, 2, or 3,
// OR 3, 4, or 5
return d;
});

Related

How can I switch from operator to another operator?

I'm making a program that can understands human words, and so far it's going great.
My current standpoint is understanding math equations. You can add, subtract, multiply and divide very easily with as many numbers as you'd like, but I'm wondering how I can do addition then multiply the result, like this:
const source = require("./source.js")
var main = source.interpret(
"add 4 and 4 multiply by 4",
)
source.output(main)
And it should output:
64
Yes I know that there is an easier way of doing this math equation, however in any calculator of any sort you should be able to this kind of switching in any context.
How can I accomplish this?
Here is the full source code;
index.js:
const source = require("./source.js")
var main = source.interpret(
"add 4 and 4 together then multiply the result by 4",
)
source.output(main)
source.js:
function output(main) {
console.log(main)
}
function interpret(str) {
const dl = str.split(' ');
const operator = dl.shift(x => x.includes("add", "subtract", "multiply", "divide"))
const numbers = dl.filter(x => Number(x))
switch (operator) {
case "add":
return numbers.reduce((a, b) => Number(a) + Number(b));
case "subtract":
return numbers.reduce((a, b) => Number(a) - Number(b));
case "multiply":
return numbers.reduce((a, b) => Number(a) * Number(b));
case "divide":
return numbers.reduce((a, b) => Number(a) / Number(b));
}
}
module.exports = {interpret, output}
The main problem with your interpret function is that after finding a single operator, it will perform that operation on all numbers and immediately return. We can’t simply reduce all the numbers using the first operation we find, because it’s possible that some numbers are related to other operations! In the expression add 2 and 2 multiply by 3, the 3 is related to the multiply operation!
This means that we can't process the entire input like that. An alternative is to iterate over the input, and depending on the operator we find, we perform the related action.
To simplify, let's consider that there's only the add operation. What are we expecting next? It could be [number] and [number], but also, it can be by [number]. The first one just adds the two numbers, but in the second, it should add the new number to the last operation.
A side note: your shift and filter functions are parsing the input, and the switch case is interpreting the parsed structure. Your “human language” is actually a programming language! add 2 and 2 is analogous to 2 + 2 in JavaScript, just different. With that, I will introduce you to some programming language theory terms, it can be easier to search for more help if you deep dive in the topic.
Considering the last paragraph, let's refactor interpret:
// from https://stackoverflow.com/questions/175739/how-can-i-check-if-a-string-is-a-valid-number
function isNumeric(str) {
if (typeof str != "string") return false
return !isNaN(str) && !isNaN(parseFloat(str))
}
function interpret(input) {
const tokens = input.split(' ') // in fancy programming language terms,
// this is a lexical analysis step
// note that we are not supporting things like
// double spaces, something to think about!
let state = 0 // we are keeping the results from our operation here
for (i = 0; i < tokens.length; i++) {
const t = tokens[i] // to keep things shorter
switch (t) {
case "add": // remember: there's two possible uses of this operator
const next = tokens[i + 1]
if (next == "by") {
// we should add the next token (hopefully a number!) to the state
state += parseFloat(tokens[i + 2])
i += 2 // very important! the two tokens we read should be skipped
// by the loop. they were "consumed".
continue // stop processing. we are done with this operation
}
if (isNumeric(next)) {
const a = tokens[i + 2] // this should be the "and"
if (a != "and") {
throw new Error(`expected "and" token, got: ${a}`)
}
const b = parseFloat(tokens[i + 3])
state = parseFloat(next) + b
i += 3 // in this case, we are consuming more tokens
continue
}
throw new Error(`unexpected token: ${next}`)
}
}
return state
}
const input = `add 2 and 2 add by 2 add by 5`
console.log(interpret(input))
There's a lot to improve from this code, but hopefully, you can get an idea or two. One thing to note is that all your operations are "binary operations": they always take two operands. So all that checking and extracting depending if it's by [number] or a [number] and [number] expression is not specific to add, but all operations. There's many ways to write this, you could have a binary_op function, I will go for possibly the least maintainable option:
// from https://stackoverflow.com/questions/175739/how-can-i-check-if-a-string-is-a-valid-number
function isNumeric(str) {
if (typeof str != "string") return false
return !isNaN(str) && !isNaN(parseFloat(str))
}
function isOperand(token) {
const ops = ["add", "multiply"]
if (ops.includes(token)) {
return true
}
return false
}
function interpret(input) {
const tokens = input.split(' ') // in fancy programming language terms,
// this is a lexical analysis step
// note that we are not supporting things like
// double spaces, something to think about!
let state = 0 // we are keeping the results from our operation here
for (i = 0; i < tokens.length; i++) {
const t = tokens[i] // to keep things shorter
if (!isOperand(t)) {
throw new Error(`expected operand token, got: ${t}`)
}
// all operators are binary, so these variables will hold the operands
// they may be two numbers, or a number and the internal state
let a, b;
const next = tokens[i + 1]
if (next == "by") {
// we should add the next token (hopefully a number!) to the state
a = state
b = parseFloat(tokens[i + 2])
i += 2 // very important! the two tokens we read should be skipped
// by the loop. they were "consumed".
}
else if (isNumeric(next)) {
const and = tokens[i + 2] // this should be the "and"
if (and != "and") {
throw new Error(`expected "and" token, got: ${and}`)
}
a = parseFloat(next)
b = parseFloat(tokens[i + 3])
i += 3 // in this case, we are consuming more tokens
} else {
throw new Error(`unexpected token: ${next}`)
}
switch (t) {
case "add":
state = a + b
break;
case "multiply":
state = a * b
}
}
return state
}
const input = `add 2 and 2 add by 1 multiply by 5`
console.log(interpret(input)) // should log 25
There's much more to explore. We are writing a "single-pass" interpreter, where the parsing and the interpreting are tied together. You can split these two, and have a parsing function that turns the input into a structure that you can then interpret. Another point is precedence, we are applying the operation in the order they appear in the expression, but in math, multiplication should be done first than addition. All of these problems are programming language problems.
If you are interested, I deeply recommend the book http://craftinginterpreters.com/ for a gentle introduction on writing programming languages, it will definitely help in your endeavor.

Remove Array Json object elements

Here I have two arrays
var arry1 = [{id:1,name:"muni"},{id:2,name:"Anji"}, {id:3,name:"vinod"},{id:4,name:"anil"}];
var arry2 = [{id:3},{id:1}];
I want the following results
arry1= [{id:2,name:"Anji"},{id:4,name:"anil"}]
Should be remove second selected elements in first array
You can use Array.filter to remove any element that is present in arry2. We can create a Set of id elements to filter out, this will be more efficient for larger arrays:
var arry1 = [{id:1,name:"muni"},{id:2,name:"Anji"}, {id:3,name:"vinod"},{id:4,name:"anil"}];
var arry2 = [{id:3},{id:1}];
// Filter out any elements in arry1 that are also present in arry2, first create a Set of IDs to filter
const idsToFilter = new Set(arry2.map(el => el.id));
const result = arry1.filter(el => !idsToFilter.has(el.id));
console.log("Result:", result)
While removing from an array, you should iterate backwards over it.
for (let i = arry1.length - 1; i >=0; i--) {
...
}
This ensures that no elements are skipped after an element is removed. See also this other question for more info on this.
Now for each element of arry1 we want to check whether it should be removed.
let idsToRemove = arry2.map(e => e.id); // [3, 1]
for (let i = arry1.length - 1; i >=0; i--) {
if (idsToRemove.includes(arry1[i].id) {
// it should be removed
arry1.splice(i, 1);
}
}
Something like the above should then work for your problem. For easier understanding of the code, I first mapped arry2 to only the IDs, but of course you can also use another loop to see whether there is a match. The most important take-away is that to safely remove from an array while iterating it, you need to iterate from the last to the first element.
Try this it will work, here filter will filter out only those array element which doesn't exist in arry2
var myArray = arry1.filter(ar => !arry2.find(el => (el.id === ar.id) ))

Cassandra: How to reference a field in user defined type in a user defined function (Java)

How does one reference fields within a user defined type when using Java user defined functions. I have found examples for map, set and tuple, but not for user defined types with multiple fields.
I have the following type defined:
create type avg_type_1 (
accum tuple<text,int,double>, // source, count, sum
avg_map map<text,double> // source, average
);
The following code:
CREATE FUNCTION average_by_source_1( state avg_type_1, source text, value double)
CALLED ON NULL INPUT
RETURNS avg_type_1
LANGUAGE java
AS $$
// when no source yet, save the first source, set the count to 1, and set the value
if (state.accum.getString(0) == null) {
state.accum.setString(0, source);
state.accum.setInt(1, 1);
state.accum.setDouble(2, value);
}
...
returns the error:
InvalidRequest: Error from server: code=2200 [Invalid query] message="Java source compilation failed:
Line 4: accum cannot be resolved or is not a field
In Java the UDT variable is represented by the class com.datastax.driver.core.UDTValue. This class has get and set methods. There are methods using an index (0 ...) to identify the fields (in the order they are defined in the UDT), and methods that use the field name.
See API Doc.
Here are some examples, using the type defined in the question:
TupleValue accumState = state.getTupleValue( "accum");
String prevSource = accumState.getString( 0);
Map<String,Double> avgMap = state.getMap( "avg_map", String.class, Double.class);
The first line gets the accum field from the function's state. Instead of the name, the index 0 (zero, it is the first field) could be used.
The second line gets the first element of the tuple. Only the index version can be used, as the elements of a tuple are not named.
The third line gets the avg_map field.
accumState.setDouble( 2, value);
state.setTupleValue( "accum", accumState);
The above example sets the third element in the tuple, and then puts the tuple back into the function's state variable. Note that you have to put the tuple back into the state variable. The following does not work.
// does not work
state.getTupleValue( "accum").setDouble( 2, value);
Below is the full example UDF.
// sums up until the source changes, then adds the avg to the map
// IMPORTANT: table must be ordered by source
CREATE OR REPLACE FUNCTION average_by_source_1( state avg_type_1, source text, value double)
CALLED ON NULL INPUT
RETURNS avg_type_1
LANGUAGE java
AS $$
TupleValue accumState = state.getTupleValue( "accum");
String prevSource = accumState.getString( 0);
// when no source yet, save the first source, set the count to 1, and set the value
if (prevSource == null) {
accumState.setString( 0, source);
accumState.setInt( 1, 1);
accumState.setDouble( 2, value);
state.setTupleValue( "accum", accumState);
}
// when same source, increment the count and add the value
else if (prevSource.equals( source)) {
accumState.setInt( 1, accumState.getInt( 1) + 1);
accumState.setDouble( 2, accumState.getDouble( 2) + value);
state.setTupleValue( "accum", accumState);
}
// when different source, calc average and copy to map, then re-init accumulation
else if (accumState.getInt( 1) > 0) {
double avgVal = accumState.getDouble( 2) / accumState.getInt( 1);
Map<String,Double> mapState = state.getMap( "avg_map", String.class, Double.class);
mapState.put( prevSource, avgVal);
state.setMap( "avg_map", mapState, String.class, Double.class);
accumState.setString( 0, source);
accumState.setInt( 1, 1);
accumState.setDouble( 2, value);
state.setTupleValue( "accum", accumState);
}
// should not happen - prev case uses "if" to avoid division by zero
else {
Map<String,Double> mapState = state.getMap( "avg_map", String.class, Double.class);
mapState.put( "ERROR: div by zero", null);
accumState.setString( 0, source);
accumState.setInt( 1, 1);
accumState.setDouble( 2, value);
state.setTupleValue( "accum", accumState);
}
// IMPROTANT: final function must calculate the average for the last source and
// add it to the map.
return state;
$$
;

How can a Groovy method return multiple times?

I'm trying to get the first K elements from a sorted map by the following piece of code:
//return top rank k elements
public static LinkedHashMap<String,Double> getTopRank(int i){
//store top k elements
LinkedHashMap<String, Double> result=new LinkedHashMap<>();
int count=0;
//use the static rankMap in the class
rankMap.each {key,value->
result.put(key, value);
count++;
if(count>=i){
println "Time to return"
return result;
}
}
//in case the loop does not work
return result;
}
What I expect is that when the result Map already has a size of i elements, the method will return, giving me a i-size sorted map. Note that rankMap stores the elements in a certain order I want, and its size is far bigger than int i I pass to the method.
And I'm calling the method by
LinkedHashMap<String,Double> content=getTopRank(outputSize);
But unexpectedly finally the content had the size of rankMap rather than i! And in the console I saw hundreds of Time to return lines. The line return result was executed again and again until it reached the end of rankMap.
I'm pretty sure that the line getTopRank(outputSize) was not in a loop. Then it seems strange to me why this method can return multiple times without ending. Is it caused by my putting return statement in the closure?
Please advise or tell me how this is true in Groovy. One step further, how can I get only first k elements from a sorted map then?
You misunderstood key concepts of Groovy.
The only way to finish the each() execution before reaching the end, is to throw an exception. If your want to exit the loop conditionally, use standard loop types like for or while:
int count=0
def result = [:]
for( def e in rankMap ){
count++
result[ e.key ] = e.value
if( i <= count ) return result
}
The method itself is not returning. each is a method which receives a closure. Closures have their own returning context, which is not tied to the method who invoked them, thus, the loop is not broken.
I'd like to suggest getting a range from the map's entrySet and collecting the resulting entries:
def getTopRank(int i) {
rankMap
.entrySet()
.toList()[0..<i]
.collectEntries()
}
rankMap = [
'Beatles' : 'The White Album',
'Pink Floyd' : 'The Dark Side of the Moon',
'Rolling Stones' : 'Sticky Fingers',
'The Doors' : 'Morrison Hotel',
'Bob Dylan' : 'Bob Dylan'
]
assert getTopRank(2) == [
'Beatles' : 'The White Album',
'Pink Floyd' : 'The Dark Side of the Moon']
assert getTopRank(4) == [
'Beatles' : 'The White Album',
'Pink Floyd' : 'The Dark Side of the Moon',
'Rolling Stones' : 'Sticky Fingers',
'The Doors' : 'Morrison Hotel',]
public static LinkedHashMap<String,Double> getTopRank(int i){
rankMap.take(i)
}
http://www.groovy-lang.org/gdk.html
http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Map.html#take(int)

Common Elements Sequence

I have two arrays of integer type.
int[] righttarray=new int[] {6,9,8,1,5,3};
int[] leftarray=new int[] {1,3};
Now I have to find out the common elements between these two as well as I need to match common elements indexes. If the indexes are same then its ok, if not then sequence will be maintained from rightarray.
I am getting Common elements by intersect method in C#.
See, element 1 and 3 are common in both the arrays. But in "leftarray" their sequence in 0,1 and in "rightarray" their sequence in 3,5. How to check this is my question. Thanks !!
Help me out doing this.
Ok, try something like:
int[] righttarray = new int[] { 6, 3, 8, 1, 5, 3 };
int[] leftarray = new int[] { 1, 3 };
if (righttarray.Length < leftarray.Length)
{
var result = righttarray.Where((x, i) => righttarray[i] == leftarray[i]);
}
else
{
var result = leftarray.Where((x, i) => leftarray[i] == righttarray[i]);
}
This will give you the number 3, which is in the same index and with the same element number. In your example, the output will be empty, I have changed only to check it ;)

Resources