accessing arguments in callback array.protoype - javascript

I am implementing the map function. To access the array I am mapping over I am using this based on a question I had earlier. Now I am wondering how to access different arguments passed to the callback. So in the official map method you can pass the index. I am trying to do this, but unsure how to access this in my custom method.
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i]))
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
return item * 2;
})
console.log(x);

You need to hand over the index as second parameter for the callback
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i], i));
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
console.log(index, item);
return item * 2;
})
console.log(x);

You just need to add another argument to your callback function which is your index.
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i], i))
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
console.log(index);
return item * 2;
})
console.log(x);

Related

issue with rewriting the reduce method js

I am trying to rewrite the reduce method.
I have a couple of things I am unsure of. Firstly, is that it gives the wrong result, which I cannot figure out why. Secondly, if I don't assign the reducez function to a const or a let there is an error.
The following code gives an error
Cannot read property 'reducuez' of undefined
Does anyone know why this is.
[1, 2, 3].reducuez((a, b) => {
return a + b;
});
And here is the actual code where I am trying to write the reduce method.
Array.prototype.reducuez = function(callback) {
let initialValue = 0;
for (let i = 0; i < this.length; i++) {
initialValue += callback(this[i], initialValue)
}
return initialValue;
}
const y = [1, 2, 3].reducuez((a, b) => {
return a + b;
});
console.log(y); // this is 11, should be 6
initialValue += callback(this[i], initialValue)
should be
initialValue = callback(this[i], initialValue)
because when you append values after every callback the the value of initalValue is added twice once in callback and once due to +=
Array.prototype.reducuez = function(callback) {
let initialValue = 0;
for (let i = 0; i < this.length; i++) {
initialValue = callback(this[i], initialValue)
}
return initialValue;
}
const y = [1, 2, 3].reducuez((a, b) => {
return a + b;
});
console.log(y); // this is 11, should be 6

Replicate array to certain length in javascript

I have this array [1,2,3]
I would like to be able to set its length to 7
and have this [1,2,3,1,2,3,1] as a result.
Anyone?
const arr = [1,2,3];
// Something like
arr.resize(7);
console.log(arr); // [1,2,3,1,2,3,1]
EDIT:
Based on chevybow answer below i wrote this functions to serve my needs.
// Immutable
Array.prototype.resize = function(size) {
const array = Array(size);
for(let i = 0; i < size; i++) {
array[i] = this[i%this.length];
}
return array;
}
// Mutable
Array.prototype.resize = function(size) {
const array = this.slice(0);
this.length = size;
for(let i = 0; i < size; i++) {
this[i] = array[i%array.length];
}
}
Are those ok? or you think that putting it on the chain is not a good idea, if so why?
You can use modular arithmetic to loop through up to the length of your final array and then use the index to basically loop through and push that onto a new array
Using the current array value % array.length will get you the current position of the array by progressing it in a circular motion
let num = 7;
let array = [1,2,3];
let result = [];
for(let i = 0; i < num; i++){
result.push(array[i%array.length]);
}
console.log(result)
A simple while loop would suffice:
function repeat(arr, toLength) {
let output = [...arr];
while (output.length < toLength) output = [...output, ...arr];
return output.slice(0, toLength);
}
console.log(repeat([1, 2, 3], 7));
console.log(repeat([1, 2, 3], 2));
How about this version:
const nums = [1, 2, 3];
function resize(arr, length) {
let position = 0;
return Array.from(Array(length)).reduce((acc, _, i) => {
return acc.concat(arr[i % arr.length]);
}, []);
}
console.log(resize(nums, 7));

JS delete duplicated items from array without higher order functions

I know it's a stupid question, but I only learning programming 3 months now.
How would you solve this problem, if you can't use higher order functions and built-in methods, like filter or indexOf?
Create a function that takes a list of numbers and returns a new list where all the duplicate values are removed
I got this so far, but I think It's a dead end...
const array = [1, 2, 3, 3, 1];
const removeDuplicate = () => {
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length; j++) {
if (i != j) {
if (array[i] == array[j]) {
shortArray[index] += array[i]
console.log(array[i]);
}
}
}
}
return shortArray;
}
console.log(removeDuplicate());
return this:
1
3
3
1
[ NaN ]
thanks!
Use an object as a helper. If a value appears in the helper, it's not unique and can be ignored. If it's not in the helper it's unique, push it into the result array, and add it to the helper object.
const array = [1, 2, 3, 3, 1];
const removeDuplicate = (arr) => {
const helperMap = {};
const result = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (!helperMap[item]) {
result[result.length] = item;
helperMap[item] = true;
}
}
return result;
};
console.log(removeDuplicate(array));
function unique(arr) {
var obj = {};
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
obj[value] = true; // set as key
}
return Object.keys(obj); //return all keys
}
Use below function:
function RemoveDuplicate(array){
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
let exist=false;
for(let j=0;j<shortArray.length;j++){
if(array[i]==shortArray[j]){
exist=true;
break;
}
}
if(!exist){
shortArray[shortArray.length]=array[i];
}
}
return shortArray;
}

How delete from array all same elements?

How can I delete all same elements from array if
for exsample I have
var arr = [1,1,1,2,3,4,5,6,7];
I need to get array like this
[2,3,4,5,6,7];
I' using this
var chotch = 0;
for(var i = 0; i < text1_arr.length; i++) {
if(word1_reg.test(text1_arr[i])) {
text1_arr.splice(i, 1);
chotch++;
if(needCount === chotch) {
break;
}
} else {
continue;
}
}
Following code returns array just elements which occurs only once.
ES6 solution.
var arr = [1,1,1,2,2,3,4,5];
(function cleanIt(arr) {
var arr2 = arr.filter((v, i) => arr.indexOf(v) != i);
var newArr = arr.filter(v => !arr2.includes(v));
console.log(newArr);
console.log(`Elements deleted: ${arr.length-newArr.length}`);
})(arr);
ES5 solution. Note: Array#includes is ES6 feature.
var arr = [1,1,1,2,2,3,4,5];
(function cleanIt(arr) {
var arr2 = arr.filter(function(v,i) {
return arr.indexOf(v) != i;
});
var newArr = arr.filter(function(v) {
return !arr2.includes(v);
});
console.log(newArr);
console.log('Elements deleted: ' + (arr.length - newArr.length));
})(arr);
function removeDuplicates(input){
var out = [];
var duplicates = [];
input.forEach(function(item){
if(duplicates.indexOf(item)!==-1)return;
var outIndex = out.indexOf(item)
if(outIndex!==-1){
out.splice(outIndex,1)
duplicates.push(item);
return;
}
out.push(item)
});
return out;
}
removeDuplicates([1,1,1,2,3,4,5,6,7]) // [2, 3, 4, 5, 6, 7]
You can iterate over your array and check for every item that it exists only once using use indexOf and lastIndexOf. If yes, then add it to a result array.
var arr = [1,1,1,2,3,4,5,6,7];
var result = [];
for (var i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) === arr.lastIndexOf(arr[i])) {
result.push(arr[i]);
}
}
This strategy eliminates any element that can be found 2 times.
const arr = [1,1,1,2,3,4,5,6,7];
const uniqs = a => a.filter(e => a.slice(a.indexOf(e) + 1).indexOf(e) === -1);
console.log(uniqs(arr));

"Filter" or "Map" the same array using different tests without looping multiple times?

For example I have
var nums = [1,2,3,4,5,6,7,8,9];
Is there a way to write this:
var multiplesOf2 = nums.filter(...)
var multiplesOf3 = nums.filter(...)
var greaterThan7 = nums.filter(...)
And have it be as efficient as
var multiplesOf2 = [], multiplesOf3 = [], greaterThan7 = [];
nums.forEach(function (num) {
if (...) { multiplesOf2.push(num); }
if (...) { multiplesOf3.push(num); }
if (...) { greatherThan7.push(num); }
})
?
Here's one way to do it:
var LazyArray = defclass({
constructor: function (xs) {
this.xs = xs;
this.fs = [];
},
iterate: function () {
var xs = this.xs, m = xs.length;
var fs = this.fs, n = fs.length;
for (var i = 0; i < m; i++) {
var x = xs[i];
for (var j = 0; j < n; j++) {
var f = fs[j], p = f(x, i, xs);
if (p) fs.splice(j--, 1), n--; // break out of the loop
}
}
fs.length = 0;
},
filter: function (f) {
var ys = [];
this.fs.push(function (x) {
if (f(x)) ys.push(x);
});
return ys;
}
});
Here's how you would use it:
var nums = new LazyArray([1,2,3,4,5,6,7,8,9]);
var multiplesOf2 = nums.filter(...);
var multiplesOf3 = nums.filter(...);
var greaterThan7 = nums.filter(...);
nums.iterate();
Note however that performance-wise there's no real benefit. If the input array has m items and there are n calls to filter then:
Traditionally you would loop through m items n times.
In this case you're looping through n iterators m times.
In either case the time complexity is O(m * n). There's no real benefit of lazy evaluation unless you get to skip a few computations which you would otherwise unnecessarily have to do using strict evaluation.
P.S. You can extend the LazyArray class with functions for map, reduce, etc. just as easily.
Edit: I forgot the definition of defclass:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
That's all folks.
I can only guess that you want the .forEach() to be a little cleaner. You can use .reduce() if you think it helps.
var res = nums.reduce(function (obj, num) {
if (...) { obj[2].push(num); }
if (...) { obj[3].push(num); }
if (...) { obj[7].push(num); }
return obj;
}, {2:[],3:[],7:[]});
In ECMAScript 6, you'll be able to assign results to individual variables using destructuring assignment.
let {2:two, 3:three, 7:seven} = nums.reduce(function (obj, num) {
if (...) { obj[2].push(num); }
if (...) { obj[3].push(num); }
if (...) { obj[7].push(num); }
return obj;
}, {2:[],3:[],7:[]});
You'd need to test the performance, but perhaps something like this will work if you want to pass in functions
function filters(list /* test, test, test*/) {
var i, j, arr = [], tests;
tests = Array.prototype.slice.call(arguments, 1);
j = tests.length;
for (i = 0; i < j; ++i) arr[i] = [];
list.forEach(function (element, index, array) {
var i;
for (i = 0; i < j; ++i)
if (tests[i](element, index, array))
arr[i].push(element);
});
return arr;
}
filters(
[1, 2, 3, 4, 5, 6, 7, 8, 9], // first arg the Array
function (e) {return 0 === e % 2;}, // any number of tests to filter
function (e) {return 0 === e % 3;},
function (e) {return e > 7;}
);
/*
[
[2, 4, 6, 8],
[3, 6, 9],
[8, 9]
]
*/

Categories