Adding a vector to another vector without a loop - javascript

I have two Javascript vectors, a and b, of the same length. I want to add b to a. The obvious way is:
for (i=0; i<a.length; ++i)
a[i] += b[i]
but this requires a loop. I can do:
a.forEach(function(item,index) {
a[index] += b[index]
})
but this is cumbersome - it requires an unneeded parameter "item". Is there a shorter option? Maybe using some external library?

There is no built-in JS function to do this without looping. Further any library that implements this is going to use looping to do it also.
So, write yourself a short utility function and then just call that function whenever you want to do this. There's going to be looping somewhere in order to implement this as it is not a native JS feature. If you want to "hide" the looping, then just put it in a utility function and just call the function when you need it.
// returns a new array that is the sum of the two vector arrays
function addVectors(a, b) {
return a.map(function(item, index) {
return item += b[index];
});
}
Or, if you want one array modified in place:
// add one vector to another, modifying the first one
function addToVector(a, b) {
a.forEach(function(item, index) {
a[index] += b[index];
});
return a;
}
Or, if the unused item argument bothers you for some reason:
// add one vector to another, modifying the first one
function addToVector(a, b) {
for (var i = 0; i < a.length; i++) {
a[i] += b[i];
}
return a;
}
Note, all of these functions assume a and b are the same length. You would have to specify what you want the behavior to be if they end up not being the same length and you want to check for that. You could throw an exception, just add the parts in common, etc...
For example:
// returns a new array that is the sum of the two vector arrays
function addVectors(a, b) {
if (a.length !== b.length) {
throw new Error("Vector arrays must be the same length to add them");
}
return a.map(function(item, index) {
return item += b[index];
});
}

Are you sure you want to do it without the loop? Ok well:
a.forEach(function(currentElement, Index){
b[Index] += currentElement;
});

Related

How can create a function like findSum([1,2,3,5], 5) that second param is the sum of to element of array and return those two element in javascript?

I wanna write a function that receive two parameter that first one is an array and the second is an integer; So I wanna return two element of the array that their sum be equal the second function's parameter. For example in this case findSum([1,2,3,5], 5) my function will return 2 and 3 that their sum being 5. I wrote a function but I think it can be better with another optimized coding.
function findSum(arr, sum){
for(element of arr) {
const first_element = element;
for(innerElement of arr){
if((innerElement !== first_element) && (innerElement + element === sum) )
return {first_element, innerElement}
}
}
}
So, one clear issue with your code is that findSum([2,2,3],4) won't work, because of this line: if((innerElement !== first_element). You should check indexes, rather than values to avoid this.
Very quick example:
findSum = (arr, sum) => {
return arr.map((x, i) => {
return arr.map((y, j) => {
if(i === j) return null;
return x + y === sum ? {x, y} : null;
}).filter(x => x);
}).flat()[0];
}
Essentially, what I''m doing is very similar to your original version, with some slight tweaks.
Rather than using two for loops like you, I use two maps to iterate over the array. This gives me access to the index (i & j).
If i === j then it's the exact same element (and not just the same value) so we can ignore it. This solves the if((innerElement !== first_element)
issue.
Then I check to see if the sum is correct and return the values, or null if it's incorrect. Filtering this array with filter(x => x) returns only the truthy elements, i.e. removes the nulls so we are left with all the matches.
We then flatten the array and return the first object as that's all we need, but we could change that to return all the matches. findSum([2,2,1,3], 4) has two matches for example.
Key concepts:
Array.map
Array.filter
Array.flat

Looking for a function that takes three arguments (x, y, z) and checks if the type of all three is a string

Don't know what to put before the for loop. Don't know if I need an if/else statement. Trying to have it display in the console if items in an array are strings. So I know I need consol.log
var stringOne = isString('rob','bob','carl')
function isString() {
//I dont know what to put before for loop
for(let i = 0; i < arguments.length; i++) {
// Dont know if i need an if/else statement
// Trying to have it display in the console if items in an array are strings
// So I know I need consol.log
}
}
every would be appropriate here, and doing I/O (like console.log) is better left outside of the function. The name of the function suggests that it should return a boolean (true/false):
function isString(...args) {
return args.every(s => typeof s === "string");
}
console.log(isString('rob','bob','carl'));
Because it seems like you're a beginner, I will expand upon the code that you currently have, although #trincot did the best solution.
In a for loop, you can return a value so the loop won't continue. Because you only need to check if any of them are false, may it be in position 0, 1 or 2 in the array, you can return "false" immediately.
If there are only strings, the loop will continue until it ends, and then return "true" at the end of the method.
So you don't need any code before the for loop, only an if statement that returns "false" if any of the items in the array isn't a string.
var stringOne = isString('rob','bob','carl')
var stringTwo = isString('rob','bob', 1)
function isString() {
for(let i = 0; i < arguments.length; i++) {
if (typeof arguments[i] != 'string') {
return false
}
}
return true
}
console.log({stringOne});
console.log({stringTwo});
Something like this in the loop ought to do it:
this_arg = arguments[i];
if (typeof this_arg === 'string') console.log("arg number " + i + " is a string");
It shows how to do it a bit here
You may find every useful here. It iterates over the array you've made from the arguments and checks to see if each element matches the condition. If they all match it returns true, otherwise false.
function isString() {
return Array.from(arguments).every(str => {
return typeof str === 'string';
});
}
console.log(isString('rob','bob','carl'));
console.log(isString(2,'bob','carl'));

Javascript Map and Reduce with Sort [duplicate]

This simple javascript
var x = new Array();
x[0] = 2.73;
x[1] = 11.17;
x[2] = 3.12
x.sort();
for(var i in x)
alert(x[i]);
produces the results:
11.17, 2.73, 3.12 instead of 2.73, 3.12, 11.17.
Why is that and how can I fix it?
Thanks in advance!
It's sorting alphabetically, try passing your own sorting function:
var x = new Array();
x[0] = 2.73;
x[1] = 11.17;
x[2] = 3.12;
numberSort = function (a,b) {
return a - b;
};
x.sort(numberSort);
for(var i in x) {
alert(x[i]);
}
By default, Array.sort will sort alphabetically (lexographically)...but you can supply your own function. Try:
x.sort(function(a, b) { return a > b ? 1 : -1});
Array.sort() function treats its elements as Strings and if no function is passed to the sort() statement, it converts the elements to Unicode and sorts. Therefore, it is advised to pass a custom sort Function whenever sorting numbers.
function customSort(a, b){
return a - b;
}
console.log([-11,-2, 0 ,100].sort(customSort));
This customSort() function will sort the array in_place in ascending order.
Between them, the existing answers tell you everything, but none of them mention both of the problems in your code. Here's the full answer:
The sort isn't doing what you want because the default sort is lexical (i.e. the array elements are converted to strings and compared alphabetically). You can provide your own comparison function to sort():
x.sort(function(a, b) {
return a - b;
});
Secondly, for...in is actually telling you nothing concrete about whether your array is sorted correctly, because the enumeration of for...in is not defined (even though most but not all browsers do broadly what you'd expect). Use a for loop instead (as indeed you generally should for arrays):
for (var i = 0, len = x.length; i < len; ++i) {
alert(x[i]);
}
You are not iterating properly. It should be:
for (var i = 0; i < x.length; i++) {
alert(x[i]);
}
When you use for..in in javascript this will loop through the properties of the object and the order of iteration is undefined. You should be seeing some strange output as well such as all the functions defined in the Array class.

Append array element only if it is not already there in Javascript

I need to add an element to an array only if it is not already there in Javascript. Basically I'm treating the array as a set.
I need the data to be stored in an array, otherwise I'd just use an object which can be used as a set.
I wrote the following array prototype and wanted to hear if anyone knew of a better way. This is an O(n) insert. I was hoping to do O(ln(n)) insert, however, I didn't see an easy way to insert an element into a sorted array. For my applications, the array lengths will be very small, but I'd still prefer something that obeyed accepted rules for good algorithm efficiency:
Array.prototype.push_if_not_duplicate = function(new_element){
for( var i=0; i<this.length; i++ ){
// Don't add if element is already found
if( this[i] == new_element ){
return this.length;
}
}
// add new element
return this.push(new_element);
}
If I understand correctly, you already have a sorted array (if you do not have a sorted array then you can use Array.sort method to sort your data) and now you want to add an element to it if it is not already present in the array. I extracted the binary insert (which uses binary search) method in the google closure library. The relevant code itself would look something like this and it is O(log n) operation because binary search is O(log n).
function binaryInsert(array, value) {
var index = binarySearch(array, value);
if (index < 0) {
array.splice(-(index + 1), 0, value);
return true;
}
return false;
};
function binarySearch(arr, value) {
var left = 0; // inclusive
var right = arr.length; // exclusive
var found;
while (left < right) {
var middle = (left + right) >> 1;
var compareResult = value > arr[middle] ? 1 : value < arr[middle] ? -1 : 0;
if (compareResult > 0) {
left = middle + 1;
} else {
right = middle;
// We are looking for the lowest index so we can't return immediately.
found = !compareResult;
}
}
// left is the index if found, or the insertion point otherwise.
// ~left is a shorthand for -left - 1.
return found ? left : ~left;
};
Usage is binaryInsert(array, value). This also maintains the sort of the array.
Deleted my other answer because I missed the fact that the array is sorted.
The algorithm you wrote goes through every element in the array and if there are no matches appends the new element on the end. I assume this means you are running another sort after.
The whole algorithm could be improved by using a divide and conquer algorithm. Choose an element in the middle of the array, compare with new element and continue until you find the spot where to insert. It will be slightly faster than your above algorithm, and won't require a sort afterwards.
If you need help working out the algorithm, feel free to ask.
I've created a (simple and incomplete) Set type before like this:
var Set = function (hashCodeGenerator) {
this.hashCode = hashCodeGenerator;
this.set = {};
this.elements = [];
};
Set.prototype = {
add: function (element) {
var hashCode = this.hashCode(element);
if (this.set[hashCode]) return false;
this.set[hashCode] = true;
this.elements.push(element);
return true;
},
get: function (element) {
var hashCode = this.hashCode(element);
return this.set[hashCode];
},
getElements: function () { return this.elements; }
};
You just need to find out a good hashCodeGenerator function for your objects. If your objects are primitives, this function can return the object itself. You can then access the set elements in array form from the getElements accessor. Inserts are O(1). Space requirements are O(2n).
If your array is a binary tree, you can insert in O(log n) by putting the new element on the end and bubbling it up into place. Checks for duplicates would also take O(log n) to perform.
Wikipedia has a great explanation.

Three map implementations in javascript. Which one is better?

I wrote a simple map implementation for some task. Then, out of curiosity, I wrote two more. I like map1 but the code is kinda hard to read. If somebody is interested, I'd appreciate a simple code review.
Which one is better? Do you know some other way to implement this in javascript?
var map = function(arr, func) {
var newarr = [];
for (var i = 0; i < arr.length; i++) {
newarr[i] = func(arr[i]);
}
return newarr;
};
var map1 = function(arr, func) {
if (arr.length === 0) return [];
return [func(arr[0])].concat(funcmap(arr.slice(1), func));
};
var map2 = function(arr, func) {
var iter = function(result, i) {
if (i === arr.length) return result;
result.push(func(arr[i]));
return iter(result, i+1);
};
return iter([], 0);
};
Thanks!
EDIT
I am thinking about such function in general.
For example, right now I am going to use it to iterate like this:
map(['class1', 'class2', 'class3'], function(cls) {
el.removeClass(cls);
});
or
ids = map(elements, extract_id);
/* elements is a collection of html elements,
extract_id is a func that extracts id from innerHTML */
What about the map implementation used natively on Firefox and SpiderMonkey, I think it's very straight forward:
if (!Array.prototype.map) {
Array.prototype.map = function(fun /*, thisp*/) {
var len = this.length >>> 0; // make sure length is a positive number
if (typeof fun != "function") // make sure the first argument is a function
throw new TypeError();
var res = new Array(len); // initialize the resulting array
var thisp = arguments[1]; // an optional 'context' argument
for (var i = 0; i < len; i++) {
if (i in this)
res[i] = fun.call(thisp, this[i], i, this); // fill the resulting array
}
return res;
};
}
If you don't want to extend the Array.prototype, declare it as a normal function expression.
As a reference, map is implemented as following in jQuery
map: function( elems, callback ) {
var ret = [];
// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0, length = elems.length; i < length; i++ ) {
var value = callback( elems[ i ], i );
if ( value != null )
ret[ ret.length ] = value;
}
return ret.concat.apply( [], ret );
}
which seems most similar to your first implementation. I'd say the first one is preferred as it is the simplest to read and understand. But if performance is your concern, profile them.
I think that depends on what you want map to do when func might change the array. I would tend to err on the side of simplicity and sample length once.
You can always specify the output size as in
var map = function(arr, func) {
var n = arr.length & 0x7fffffff; // Make sure n is a non-neg integer
var newarr = new Array(n); // Preallocate array size
var USELESS = {};
for (var i = 0; i < n; ++i) {
newarr[i] = func.call(USELESS, arr[i]);
}
return newarr;
};
I used the func.call() form instead of just func(...) instead since I dislike calling user supplied code without specifying what 'this' is, but YMMV.
This first one is most appropriate. Recursing one level for every array item may make sense in a functional language, but in a procedural language without tail-call optimisation it's insane.
However, there is already a map function on Array: it is defined by ECMA-262 Fifth Edition and, as a built-in function, is going to be the optimal choice. Use that:
alert([1,2,3].map(function(n) { return n+3; })); // 4,5,6
The only problem is that Fifth Edition isn't supported by all current browsers: in particular, the Array extensions are not present in IE. But you can fix that with a little remedial work on the Array prototype:
if (!Array.prototype.map) {
Array.prototype.map= function(fn, that) {
var result= new Array(this.length);
for (var i= 0; i<this.length; i++)
if (i in this)
result[i]= fn.call(that, this[i], i, this);
return result;
};
}
This version, as per the ECMA standard, allows an optional object to be passed in to bind to this in the function call, and skips over any missing values (it's legal in JavaScript to have a list of length 3 where there is no second item).
There's something wrong in second method. 'funcmap' shouldn't be changed to 'map1'?
If so - this method loses, as concat() method is expensive - creates new array from given ones, so has to allocate extra memory and execute in O(array1.length + array2.length).
I like your first implementation best - it's definitely easiest to understand and seems quick in execution to me. No extra declaration (like in third way), extra function calls - just one for loop and array.length assignments.
I'd say the first one wins on simplicity (and immediate understandability); performance will be highly dependent on what the engine at hand optimizes, so you'd have to profile in the engines you want to support.

Categories

Resources