Jquery test suite does not pass - javascript

I'm the beginner in the jquery and functional programming
I transformed the jquery function into the functional programming paradigm and the following one is the original jquery function
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
for ( ; j < len; j++ ) {
first[ i++ ] = second[ j ];
}
first.length = i;
return first;
},
And I transformed that like
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
let main = (first,second)=>
{return R.concat(first, second);}
first.length = i;
return main(first,second)
},
But Jquery test suite does not pass.
It just passes up to test number 5
(ready: Error in ready callback does not halt all future executions (gh-1823) (1))
and does not pass from test 6.
I think my code has some side effects. But I cannot guess.
Is there anyone who can find it?

While the answer to your other question shows how you can write this function more simply, and while we don't have enough information to know why your test suite is failing (next time include the test that is failing), we can look at your function. Slightly reformatted, this is
const merge = function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
let main = (first,second) => {
return R.concat(first, second);
}
first.length = i;
return main(first,second)
}
Now let's simplify that. Your return statement is return main(first, second). And that main function does not depend at all upon len, j, or i, and resetting first.length to the value that was just set from first.length does nothing. So this can be just as easily written as
const merge = function( first, second ) {
let main = (first,second) => {
return R.concat(first, second);
}
return main(first,second)
}
But now note that your helper function, has nothing in its closure except for the parameters to the outer function, and those are shadowed by its own parameters. Which means that you can eliminate it entirely, and just use its body.
So we get to
const merge = function( first, second ) {
return R.concat(first, second);
}
And finally, functions of the format function(p1, p2, ..., pn) {return anotherFunc(p1, p2, ..., pn);} aren't doing anything more than renaming anotherFunc..
So in the end, you can just write
const merge = R.concat
I don't know why your function had that additional work, but it was all unnecessary. I can't see how any of it would cause the test suite to fail, as you did write a function that should still work, and there are no obvious side-effects, but perhaps the test system actually tracked the change to the length of its parameters. That would be unusual, but certainly possible.

I can't see anything from your code what might cause that error. The code relating to that test case in jQuery should be completely unrelated.
That said, one of the differences between the two functions is that the jQuery merge inserts the elements of second onto the end of the first array instance. R.concat however treats the arguments as immutable, returning a new array containing all the elements of first and second leaving the original first and second arrays unmodified. n.b. This will produce differences in behaviour if the in-place modification of the array in the jQuery function is relied upon.
On a side note, your second example can also be simplified like so:
merge: function( first, second ) {
return R.concat(first, second);
}
Or more simply:
merge: R.concat

Related

Variable loses value

So I've read many problems on here about people losing their variable's value, and it has something to do with closure. But I am completely unable to identify the problem here. I've tried with for loops, while loops, neither works.
function parseArray(arrayIn) {
var firstRow = arrayIn.shift();
while ( arrayIn.length > 0 ) {
addToTable(firstRow, arrayIn.shift());
}
}
I've also tried
function parseArray(arrayIn) {
var firstRow = Object.assign([], arrayIn[0]);
for ( var i=1; i<arrayIn.length; i++) {
addToTable(firstRow, arrayIn[i]);
}
}
Either way, addToTable is called twice correctly, and on the third pass, firstRow is an empty array. I originally tried sending arrayIn[0] which also became an empty array on the third pass. The strangest thing is, the second value (arrayIn.shift() or arrayIn[i]) is the correct and expected value the whole time.
This is probably something simple I'm just missing, but, can anyone help? I've been unable to see how other answers to do with closure apply to this case.
How do I get around this so that firstRow is always the same on each call to addToTable()? – Jesse Fogel
Well if you cannot change the method addToTable() at all. Here is what I would try:
function parseArray(arrayIn) {
var firstRow = arrayIn.shift();
while ( arrayIn.length > 0 ) {
var copy = firstRow.slice();
addToTable(copy, arrayIn.shift());
}
}
This is how to copy an array by value( not reference): as noted here: Copying array by value in JavaScript
You should start your loop from 0 not 1:
function parseArray(arrayIn) {
var firstRow = Object.assign([], arrayIn[0]);
for ( var i=0; i<arrayIn.length; i++) {
addToTable(firstRow, arrayIn[i]);
}
}
The solution to this is as follows: rather than using Object.assign to set the value of firstRow, use Object.assign to call addToTable()
e.g.
function parseArray(arrayIn) {
firstRow = arrayIn[0];
for ( var i=1; i<arrayIn.length; i++ ) {
addToTable(Object.assign([], firstRow), arrayIn[i]);
}
}

Is there a simple way to quickly pass the entire contents of a given array into an `Array.prototype` method variable without using parameters?

context
I created an array docket to keep track of coordinates as the user clicks on a canvas space. During the main program loop the array is to be scanned by a draw function so that selected pixels can be seen. Originally, inside of my event listener, I was using the push( ) method but then I realized I wanted a way to sort of toggle the pixels.
code description
So I added a method poke( ) to Array.prototype, as seen below, which allows me to push the whole docket array into a local array param.array and assign the trigger coordinate to a local variable param.entry. entry is then pushed into array and array is processed by the main poke( ) loop to ensure there are no duplicate values. If a match is found, both elements are annihilated and param.array is returned to the top, ultimately shrinking docket by 1; If no matches are found then no elements are annihilated and param.array is returned to the top, ultimately expanding docket by 1.
main issue: example 1
Anyway, as the method is currently written, it must be called thusly:
docket.poke( docket, e.key ); Note: for simplicity I have used keyboard key values.
Array.prototype.poke = function( a, b ) {
var bool = { }, i = { }, param = { };
param.array = a; param.entry = b;
//
param.array.push( param.entry );
i.len = param.array.length;
i.end = i.len - 1;
//
for ( i.cur = 0; i.cur < i.len; i.cur++ ) {
bool.match = param.array[ i.cur ] == param.array[ i.end ];
bool.nSelf = !( i.cur == i.end );
//
if ( bool.match && bool.nSelf ) {
param.array.splice( i.end, 1 );
param.array.splice( i.cur, 1 );
//
i.end -= 2;
i.len -= 2;
}
}
//
return param.array;
}
This seems a little redundant, but it offers two critical advantages. First to readability and aesthetic. Being able to visibly pass off the contents of docket to a local array for processing and then visibly return the results to the top I think is very helpful to comprehension. Second, both this example and the next use a sort of confusing truth test to filter out false positives on duplicate value detection. This example doesn't have too though. It could easily be rewritten to compare each element in param.array to param.entry using a tight, no nonsense for loop.
main issue: example 2
docket.poke( e.key ); is the less redundant and more desired approach. This is my code.
Array.prototype.poke = function( a ) {
var bool = { }, entry = a, i = { };
//
this.push( entry );
i.len = this.length;
i.end = i.len - 1;
//
for ( i.cur = 0; i.cur < i.len; i.cur++ ) {
bool.match = this[ i.cur ] == this[ i.end ];
bool.nSelf = !( i.cur == i.end );
//
if ( bool.match && bool.nSelf ) {
this.splice( i.end, 1 );
this.splice( i.cur, 1 );
//
i.end -= 2;
i.len -= 2;
}
}
}
As you can see, this eliminates the the redundancy in the call, but it sacrifices some readability of the method and more importantly the opportunity to really slim up the code using the simple comparison I mentioned above.
So now I'm wondering if there is some less than obvious way that I've missed which will allow me to pass the full contents of my array to a local variable without having to first pass them in as a parameter of its own method.
Any ideas?
There is no reason to define the method on the prototype if you are going to pass the array as an argument. A plain function would be just fine for that.
The second version of your code has indeed the advantage that you can apply the method to a given array instead of passing the array to a function.
The code could however be simplified if:
You would only add the element after you have determined it does not yet occur in the array
You would use indexOf:
Array.prototype.toggle = function(value) {
var index = this.indexOf(value);
if (index > -1) {
this.splice(index, 1);
} else {
this.push(value);
}
}
var a = [4,2,5,8];
a.toggle(2);
console.log(a.join());
a.toggle(2);
console.log(a.join());
NB: I personally find the name toggle more telling than poke.
Consider also the power of a Set: it will find an existing member in constant time (while an array implementation needs linear time), and will also be able to remove it in constant time. So if you are open to using something else than an array for this, go for a Set.
Set.prototype.toggle = function(value) {
if (!this.delete(value)) this.add(value);
}
var a = new Set([4,2,5,8]);
a.toggle(2);
console.log([...a].join());
a.toggle(2);
console.log([...a].join());

Cleanest way to use multiple values in a complex routine?

See the following pseudocode snippet that approximates my situation:
function foo () {
for ( velocity=0; velocity<100; velocity++ ) {
root1 = computeRoot1();
root2 = computeRoot2();
// do a bunch of computation with root1
// if result of computation is undesirable, do computations again with root2
}
So, basically I want to do the computations in the body of the for loop with root1, and then root2 if root1's computation result is invalid.
My first instinct was the obvious approach, to wrap the computation in a help function, but I'm not sure this is the most clear approach. I'm trying for good collocation of information in my code, and a function call for code that will be executed at most twice (per iteration) defeats that goal without providing a great deal of conciseness to my code.
I was thinking perhaps a for loop like:
for ( root=root1; root1IsInvalid==true || bothRootsInvalid==true; root=root2 )
or a while with similar functionality. But I'm certainly open to other suggestions
As someone reading this code, which approach would make it the most readable and concise to you?
As an aside, I'm writing this particular function in JavaScript, but language-agnostic solutions would be awesome.
EDIT: clarified code snippet
You have several basic approaches:
Put the values in an array and use a for loop to run the same code on each item in the array, perhaps stopping the iterations when some condition is met.
Create a function that does the computation and then just write code that calls the function on the first one, then the second one and so on.
Create a while loop and repeat your code until some condition is met.
The first option is easier to extend to N items. The second option is perhaps simpler for just two items.
You can make the computation function be a local function (declared and used inside the function you are currently executing) so it doesn't add to the global namespace and your code remains more encapsulated.
I'm also not sure what you intend to be doing with this line:
root1, root2 = computeRoots();
But, it is only assigning the value to root2 and it looks like you probably want var in front of these to define them as local variables.
If eager evaluation is OK, you can collect your roots into an array and use roots.filter(isinvalid) to take out the invalid ones; then just use the first item in the resulting array.
If you need lazy evaluation, you can generalize this into a function that lazily evaluates a function over an array until a non-null result is found:
// call fn on items in arr until fn returns non-null
// returns [item, result]
// if result===false, no true value was returned
function firstNotNull(fn, arr) {
var i, length, item, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
result = fn(item);
if (result!==null) {
break;
}
}
return [item, result];
}
function rootComputations(root) {
var computationResult = null;
if (root==1) {
computationResult = 1;
}
return computationResult;
}
function computeRoots() {
return [0,1];
}
function foo() {
var velocity, roots, root, result, computations;
for (velocity = 0; velocity < 100; velocity++) {
roots = computeRoots();
computations = firstNotNull(rootComputations, roots);
console.log(computations);
root = computations[0];
result = computations[1];
}
}
foo();
You can generalize firstNotNull() even further:
// call fn on items in arr until cond(fn(item)) returns true
// returns [item, fn(item)], or null if unsatisfied
function firstSatisfying(cond, fn, arr) {
var i, length, item, fnitem, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
fnitem = fn(item);
if (cond(fnitem)) {
result = [item, fnitem];
break;
}
}
return result;
}
var firstNotNull = firstSatisfying.bind(null, function(item){return item!==null;});
You now have a generic function for taking the first of a list of things that satisfies any condition you want.
ECMAScript 5 added many methods which make eager functional application over arrays much easier, but Javascript doesn't have any native facilities for lazy evaluation. If this is something you think you'll be needing often, consider using stream.js, which provides a "stream" datatype with methods for partial application. Using stream.js, your logic would look like this:
// rootStream should be a function which returns a Stream
// It should construct a stream with the first root produced
// and a function that returns the remaining roots.
// Since I don't know how you get your roots, I'll use a stupid example:
function rootStream() {
return new Stream(0, function(){
return new Stream(1);
});
}
function isvalid(root) {
return root===1;
}
Stream.range(0,100)
.walk(function(v){
//v doesn't seem to be used?
var firstvalid = rootStream().filter(isvalid).head();
console.log(firstvalid);
});

Can I select 2nd element of a 2 dimensional array by value of the first element in Javascript?

I have a JSON response like this:
var errorLog = "[[\"comp\",\"Please add company name!\"],
[\"zip\",\"Please add zip code!\"],
...
Which I'm deserializing like this:
var log = jQuery.parseJSON(errorLog);
Now I can access elements like this:
log[1][1] > "Please add company name"
Question:
If I have the first value comp, is there a way to directly get the 2nd value by doing:
log[comp][1]
without looping through the whole array.
Thanks for help!
No. Unless the 'value' of the first array (maybe I should say, the first dimension, or the first row), is also it's key. That is, unless it is something like this:
log = {
'comp': 'Please add a company name'
.
.
.
}
Now, log['comp'] or log.comp is legal.
There are two was to do this, but neither avoids a loop. The first is to loop through the array each time you access the items:
var val = '';
for (var i = 0; i < errorLog.length; i++) {
if (errorLog[i][0] === "comp") {
val = errorLog[i][1];
break;
}
}
The other would be to work your array into an object and access it with object notation.
var errors = {};
for (var i = 0; i < errorLog.length; i++) {
errors[errorLog[i][0]] = errorLog[i][1];
}
You could then access the relevant value with errors.comp.
If you're only looking once, the first option is probably better. If you may look more than once, it's probably best to use the second system since (a) you only need to do the loop once, which is more efficient, (b) you don't repeat yourself with the looping code, (c) it's immediately obvious what you're trying to do.
No matter what you are going to loop through the array somehow even it is obscured for you a bit by tools like jQuery.
You could create an object from the array as has been suggested like this:
var objLookup = function(arr, search) {
var o = {}, i, l, first, second;
for (i=0, l=arr.length; i<l; i++) {
first = arr[i][0]; // These variables are for convenience and readability.
second = arr[i][1]; // The function could be rewritten without them.
o[first] = second;
}
return o[search];
}
But the faster solution would be to just loop through the array and return the value as soon as it is found:
var indexLookup = function(arr, search){
var index = -1, i, l;
for (i = 0, l = arr.length; i<l; i++) {
if (arr[i][0] === search) return arr[i][1];
}
return undefined;
}
You could then just use these functions like this in your code so that you don't have to have the looping in the middle of all your code:
var log = [
["comp","Please add company name!"],
["zip","Please add zip code!"]
];
objLookup(log, "zip"); // Please add zip code!
indexLookup(log, "comp"); // Please add company name!
Here is a jsfiddle that shows these in use.
Have you looked at jQuery's grep or inArray method?
See this discussion
Are there any jquery features to query multi-dimensional arrays in a similar fashion to the DOM?

find nCr combinations for array items

I have a problem with my recursive function to find nCr objects in Array.
this works only when r=2, means only when going 1 level inside.
it seems my temporary 'a' array gets all messed up when r > 2
// find nCr combinations in Array
// n -> keys.length
// r -> number of combination to extract (cross = r-1 )
console.clear();
var keys = [0,1,2,3,4,5];
// cross = 'r'-1, s = start point, a = array
function recursive(cross, s, a){
for( var i=s; i < keys.length; i++ ){
if( !cross ){
var b = a.slice(0);
b.push( keys[i] );
set.push( b );
}
else{
a.splice(-1, 1);
a.push(keys[i]);
recursive(cross-1, i+1, a);
}
}
}
var set = [];
recursive(1, 0, []);
console.log( set );
I'm not sure what exactly you're trying to do in your else condition: note that a.splice(-1,1) removes the last element of a, but you start with a empty, when there is nothing to be removed. Even if the code works for r=2, this is a sign that you're doing something wrong. (In fact, each time you go one level deeper, a starts with just the same number of elements as it had at the previous level, so you're removing some element you shouldn't be touching.)
Here's a very slight modification of your algorithm that works correctly. I just changed the order of statements inside the else condition.
var keys = [0,1,2,3,4,5];
function recursive(cross, s, a) {
for( var i=s; i < keys.length; i++ ){
if( !cross ){
var b = a.slice(0);
b.push( keys[i] );
set.push( b );
}
else{
a.push(keys[i]);
recursive(cross-1, i+1, a);
a.splice(-1, 1);
}
}
}
var set = [];
recursive(4, 0, []);
console.log( set );
This last part should print all (6 choose 5)=6 combinations of 5 elements out of keys.
The idea is that now in each call of the function, splice only removes the element that was added in that call, rather than something added in some other function call possibly at some other level. This also guarantees that a remains the same at the end as at the beginning. (Everything you add you remove again.)
This is a common pattern you'll see when writing recursive functions: do some modification, call the function recursively, then do some cleanup that reverses the modification.
BTW, slightly cleaner code (without the cross = r-1 obfuscation) is in the first revision of this answer.

Categories