How to create an array of a given value recursively? - javascript

I'm trying to work on recursion with javascript, and I'm having trouble figuring out how to do this recursively. For example, fillArray(num, len) with num = 5, and len = 3, would return [5,5,5]. I'm honestly stuck, and I haven't been able to make progress on this. It's not much, but this is what I have. Could someone please help?
var fillArray = function(num, len) {
var list = [];
if (length === 0) {
return [];
}
return list.concat(function(value, length--));
}

This can be done easier iteratively
var fillArray = function(num, len) {
var result = [];
for (var i = 0; i < len; i++) {
result.push(num);
}
return result;
}
If you really must use recursion this should work
var fillArray = function(num, len) {
if (len === 0) {
return [];
}
return [num].concat(fillArray(num, len - 1));
}

You can do it like this, but it's not very efficient to be honest.
function arrayFill(num, length){
if(length === 0) return [];
return [].concat(num, arrayFill(num, length - 1));
}
console.log(arrayFill(5, 3));

Something like this:
var fillArray = function(num, len, list) {
list.push(num);
if (list.length === len) {
return list;
} else {
return fillArray(num, len, list);
}
}
var num = 3;
var len = 3;
var list = [];
console.log(fillArray(num, len, list));

var fillArray = function(num, len) {
var result = [];
if (len > 1) result.push(fillArray(num, len - 1));
result.push(num);
return result;
}
x = fillArray(5, 3);

An example using recursion:
function fillArray( num, length) {
var array;
if( length) {
array = fillArray( num, length-1);
array.push( num);
return array;
}
else {
return [];
}
}
The recursive function calls itself with length decremented by 1 until length is zero. Then it returns an empty array. In the return path, at each level of decreasing recursion, the value of number gets pushed onto the array.
Recursion generally requires a condition to stop further recursion (here by length - 1 reaching zero), and returning the value of the recursive call ( here the value of array).

Related

Why is the program returning undefined?

Write a mySort function which takes in an array of integers, and should return an array of the inputted integers sorted such that the odd numbers come first and even numbers come last.
So:
mySort([90, 45, 66, 'bye', '100.5'])
should return
[45, 66, 90, 100].
Here is my code:
function mySort(array) {
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length
for (var i = 0; i <= arrayLength; i++) {
if (array[i] === 'string') {
strArray = array[i].push();
}
if (Math.floor().array[i] % 2 === 0) {
evenArray = array[i].push();
}
if (Math.floor().array[i] % 2 !== 0) {
oddArray = array[i].push();
}
}
sortedArray = sort(oddArray) + sort(evenArray);
}
console.log(mySort[90, 45, 66, 'bye', 100.5]);
Several errors.
You didn't return:
function mySort(array) {
// ...
return sortedArray;
}
You should pass the parameter to Math.floor:
Math.floor(array[i]);
You should pass the parameter to array.push:
strArray.push(array[i]);
evenArray.push(array[i]);
oddArray.push(array[i]);
You should concat:
sortedArray = oddArray.concat(evenArray);
Now it at least runs.
You should use typeof: (sorts string)
if (typeof array[i] === 'string') {
// ...
}
You should use else if: (removes string)
if (typeof array[i] === 'string') {
// ...
}
else if (Math.floor(array[i]) % 2 === 0) {
// ...
}
else if (Math.floor(array[i]) % 2 !== 0) {
// ...
}
Your for loop should end earlier: (removes undefined)
for (var i = 0; i < arrayLength; i++) {
// ...
}
You should push the floor:
evenArray.push(Math.floor(array[i]));
oddArray.push(Math.floor(array[i]));
Finally, sort it in order using a comparator:
sortedArray.sort(function (a, b) { return a - b; })
Solution:
function mySort(array) {
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
if (typeof array[i] === 'string') {
strArray.push(array[i]);
}
else if (Math.floor(array[i]) % 2 === 0) {
evenArray.push(Math.floor(array[i]));
}
else if (Math.floor(array[i]) % 2 !== 0) {
oddArray.push(Math.floor(array[i]));
}
}
sortedArray = oddArray.concat(evenArray);
sortedArray.sort(function (a, b) { return a - b; });
return sortedArray;
}
console.log(mySort([90, 45, 66, 'bye', 100.5])); // [45, 66, 90, 100]
You have no return statement. JavaScript function syntax doesn't implicitly return the last expression, except to return undefined if no explicit return is present.
You should .concat() the arrays. The + doesn't do what you seem to want.
return sort(oddArray).concat(sort(evenArray));
This condition is incorrect:
if(array[i] === 'string'){
You need typeof there to check the type of the member.
if(typeof array[i] === 'string'){
Your .push() calls are wrong. I guess you meant this:
evenArray.push(array[i]);
Your recursive calls should be using mySort() instead of sort().
strArray and sortedArray are essentially being ignored.
Math.floor() expects an argument.
Math.floor(array[i])
Your loop condition is wrong. It should be i < arrayLength, not <=
Your recursion has no escape clause
Your initial call to mySort is not using parentheses to invoke it. It should be:
console.log(mySort([/*...array items...*/]));
Your if conditions should be using else. If it's a string, you don't need to test it again, assuming it is to be excluded. If it's not even, then you know it's odd, based on your criteria, so the last condition isn't needed.
You apparently want to convert strings to numbers if possible, and converted to an integer. So instead of the typeof check, you could go ahead and convert it using parseInt or + or Number, and check if it's NaN, and if so, pass it over, and if not, make sure it's converted to an integer before testing it for odd/even.
Just to note, arrow functions do have an implicit return when the function body consists of a single expression.
Here's a working example with the above corrections:
function mySort(array) {
var oddArray = [];
var evenArray = [];
var arrayLength = array.length;
for(var i = 0; i < arrayLength; i++) {
var n = Math.floor(Number(array[i]));
if (isNaN(n)) {
continue;
}
if (n % 2 === 0 ){
evenArray.push(n);
} else {
oddArray.push(n);
}
}
return oddArray.length < 1 ? evenArray :
evenArray.length < 1 ? oddArray :
mySort(oddArray).concat(mySort(evenArray));
}
console.log(mySort([90, 45, 66, 'bye', 100.5]));
With a simple improvement on #llama 's code, expected result is returned.
We just need to sort oddArray and evenArray individually.
function mySort(nums) {
'use strict'
var array = nums
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
if (typeof array[i] === 'string') {
strArray.push(array[i]);
}
else if (Math.floor(array[i]) % 2 === 0) {
evenArray.push(Math.floor(array[i]));
}
else if (Math.floor(array[i]) % 2 !== 0) {
oddArray.push(Math.floor(array[i]));
}
}
// sort oddArray
oddArray.sort(function (a, b) { return a - b; });
// sort evenArray
evenArray.sort(function (a, b) { return a - b; });
// make an array from both of them.
sortedArray = oddArray.concat(evenArray);
return sortedArray;
}

Remove characters from a string which occurs more than twice

I want to remove the third occurrence of a character from a string.
Below is what I tried from my end:
function unique(list) {
var result = [];
function findOccurrences(arr, val) {
var i, j,
count = 0;
for (i = 0, j = arr.length; i < j; i++) {
(arr[i] === val) && count++;
}
return count;
}
$.each(list, function(i, e) {
if (findOccurrences(list, e) < 3) result.push(e);
});
return result.join("");
}
var srting = "DGHKHHNL";
var thelist = srting.split("")
console.log(unique(thelist));
Here are some expected results:
Input: DGHKHHNL
Expected: DGHKHNL
Input: AFKLABAYBIB
Expected: AFKLABYBI
Input: JNNNKNND
Expected: JNNKD
https://regex101.com/r/WmUPWW/1 .. I tried using this regex as well to solve the issue. But this this doesn't solves the issue as well.
Please help
Instead of counting the occurrences, you should check the occurrence count for the specific index you are evaluating. Basically, if it's the 3rd or more time that it has appeared, then you don't want it.
A slight change to your code can achieve this (you may want to choose a better function name):
function unique(list) {
var result = [];
function findOccurrenceIndex(arr, val, index) {
var i, j,
count = 0;
for (i = 0, j = arr.length; i < j; i++) {
(arr[i] === val) && count++;
if (i == index) {
return count;
}
}
return count;
}
$.each(list, function(i, e) {
if (findOccurrenceIndex(list, e, i) < 3) result.push(e);
});
return result.join("");
}
var srting = "DGHKHHNL";
var thelist = srting.split("")
console.log(unique(thelist));
Here is a working example
Note that this answer is based on your current code, I expect you could refactor the logic to reduce the code clutter.
In fact, the following reduces the code to a single loop. It works by building a dictionary of character counts as it works though the list. (It also doesn't rely on JQuery like your original attempt):
function unique(list) {
var result = [];
var counts = {};
for (var i = 0; i < list.length; i++) {
var c = list[i];
if (!counts[c])
counts[c] = 0;
counts[c]++;
if (counts[c] < 3) {
result.push(c);
}
}
return result.join("");
}
Here is a working example
An alternate approach which doesn't rely on jQuery (although you could easily swap that with a forEach):
function unique(str) {
var count = {}
return str.split("").reduce((acc, cur) => {
if (!(cur in count)) {
count[cur] = 1;
acc.push(cur);
return acc;
}
if (count[cur] == 2) return acc;
acc.push(cur);
count[cur]++;
return acc;
}, []).join("");
}
Here I used two helper array result and tempCount . tempCount is store each alphabet as key and count it ,so if it is exceed more than 3
function unique(list) {
var result = [];
var tempCount = [];
list = list.split("");
for(var i=0;i < list.length;i++) {
if(tempCount[list[i]]) {
if(tempCount[list[i]] == 2) continue;
tempCount[list[i]]++;
} else {
tempCount[list[i]] = 1;
}
result.push(list[i]);
}
return result.join("");
}
var srting = "JNNNKNND";
console.log(unique(srting));
Building off the answer by #musefan, another ES6 approach can use Array.reduce to build the counts/output based on an accumulator object:
const onlyTwo = list => list.split('').reduce((cache, letter) => {
cache[letter] ? cache[letter]++ : cache[letter] = 1;
if (cache[letter] < 3) cache.output += letter;
return cache;
}, {
output: ''
}).output;
console.log(onlyTwo('DGHKHHNL'));
console.log(onlyTwo('AFKLABAYBIB'));
console.log(onlyTwo('JNNNKNND'));
You can improve this by applying functional programming principles to separate the concerns of counting the duplicates and generating the output string. This way you can utilize the same accumulation technique with different max values.
const maxDuplicates = max => list => list.split('').reduce((cache, letter) => {
cache[letter] ? cache[letter]++ : cache[letter] = 1;
if (cache[letter] <= max) cache.output += letter;
return cache;
}, {
output: ''
}).output;
const onlyTwo = maxDuplicates(2);
console.log(onlyTwo('DGHKHHNL'));
console.log(onlyTwo('AFKLABAYBIB'));
console.log(onlyTwo('JNNNKNND'));
const onlyOne = maxDuplicates(1);
console.log(onlyOne('DGHKHHNL'));
console.log(onlyOne('AFKLABAYBIB'));
console.log(onlyOne('JNNNKNND'));

Returning first n elements of an array Javascript

I am writing a function that will return the first n elements of an array and if n is undefined then return the first element.
*Edit: I solved the problem.
_.first = function(array, n) {
var result = [];
if (n == undefined) {
return array[0];
}
var m;
if (array.length < n) {
m = array.length;
} else {
m = n;
}
for (var i = 0; i < m; i++) {
result.push(array[i]);
} return result;
};
This program is basically checking if the n value is bigger than the array's length, if it is, then it exits.
If n is not a number it exits. If it is it executes the program and logs the values of indexes with for loop until i reaches the n value. Also, it pushes the values to the empty array, so you can get the values from the array for later use.
var arr1 = [2, 3, 4, 5, 6, 7, 8];
var arr2 = []; //empty array
function arrNreturn(arr, n){
if(typeof n != 'number'){
console.log('n is not a number');
return false; //exit the program
}
if(n > arr.length){
console.log("the n value is bigger than the length");
}else{
for(var i = 0; i < n; i++){
console.log(arr[n]);
arr2.push(arr[n]);
}
}
}
arrNreturn(arr1, 10);
1_.first = function(array, n) {
2 var result = [];
3 for (var i = 0; i < n; i++) {
4 result.push(array[i]);
5 return result;
6 } return array[0];
7};
the problem is on the 5th line, you seem to be returning the first and not taking into account the n parts
a solution might be
_first = function(array, n){
var result = [];
if(n === undefined) return array[0];
for (var i = 0; i < n; i++) {
result.push(array[i]);
}
return result;
}
Basic is
const newArr = function(arr) {return n }
Shorthand
const newArr = arr => { return n}

trying to divide negatives and positives in JavaScript

Very new, trying to make a function that takes out and separates all negatives/positives/zeros in an array. So far Ive been able to make an acceptable for loop but only with hard coded numbers. Dont currently know how to convert it into a function. please help.
var arr=[1,3,5,-9,-3,0];
var new_arr = [];
var new_arr2 = [];
var new_arr3=[];
for(i =0; i < arr.length; i++){
if(arr[i]>0){
new_arr.push(arr[i]);
}
else if(arr[i]<0){
new_arr2.push(arr[i]);
}
else if(arr[i]===0){
new_arr3.push(arr[i]);
}
}
console.log(new_arr3.length/arr.length);
console.log(new_arr2.length/arr.length);
console.log(new_arr.length/arr.length);
How about something like this?
function division(arr) {
var new_arr = [];
var new_arr2 = [];
var new_arr3 = [];
for (i = 0; i < arr.length; i++) {
if (arr[i] > 0) {
new_arr.push(arr[i]);
} else if (arr[i] < 0) {
new_arr2.push(arr[i]);
} else if (arr[i] === 0) {
new_arr3.push(arr[i]);
}
}
console.log(new_arr3.length / arr.length);
console.log(new_arr2.length / arr.length);
console.log(new_arr.length / arr.length);
}
division([1, 3, 5, -9, -3, 0]);
This new function takes the array as a parameter, so all you need to do is call it and pass the array.
You can try this way also, here I am considering 0 as a positive number. If you want, you can tweak the condition as per requirement.
function positive_negative(array ){
positive = array.filter(function (a) { return a >= 0; });
negative = array.filter(function (a) { return a < 0; });
return [positive,negative];
}
var array = [1,3,5,-9,-3,0];
console.log(positive_negative(array));

JavaScript recursive loop to sum all integers from nested array

arr will be an array, containing integers, strings and/or arrays like itself. Sum all the integers you find, anywhere in the nest of arrays.
This is what I came up with, but still not right yet
function arraySum(arr) {
var sum = 0;
var sum1 = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === Math.round(arr[i])) { //check if its an integar
sum += arr[i];
}
if (arr[i] instanceof Array) {
for (var n = 0; n < arr[i].length; n++) {
sum1 += arr[i][n];
}
}
}
console.log(sum + sum1);
}
var sumArr = [[[[[[[[[1]]]]]]]], 1]; // => 101. SHOULD BE 2
arraySum(sumArr);
function arraySum(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] instanceof Array) { sum += arraySum(arr[i]);}
if (arr[i] === Math.round(arr[i])) {sum += arr[i];}
}
return sum;
}
What about using reduce recursively?
function arrSum(arr) {
return arr.reduce(function fn(a, b) {
if (Array.isArray(b)) {
return b.reduce(fn, a);
} else if (b === Math.round(b)) {
return a + b;
}
return a;
}, 0);
}
The reduce() method applies a function against an accumulator and each
value of the array (from left-to-right) has to reduce it to a single
value.
function add(array){
return(array+"").match(/-?\d+(?:\.\d+)?/g).reduce(function(a,b) {
return +a+ +b;
});
}
That uses regex to parse a stringified array but it should work just fine.
So then there'll be an array with only the numbers. Those get parsed into a .reduce() which adds them. The best I could think of :)
help from: mdn
function add(n){return JSON.stringify(n).match(/[^\D]+/g).reduce(function(n,r){return 1*n+1*r})} is what came out of http://jscompress.com
SPEED: 0.04395800351630896s
Either 11% faster than other answers, or my Math's terrible
A more supported answer:
function add (array) {
var nums = JSON.stringify(array).match(/[\d\-]+/g),
i,
sum = 0;
for (i = 0; i < nums.length; i += 1) {
sum += parseInt(nums[i], 10);
}
return sum;
}
You can solve this using recursive functions, try with something like this:
function arraySum(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === Math.round(arr[i])) {
sum += arr[i];
}
if (arr[i] instanceof Array) {
sum += arraySum(arr[i]); //This will apply the same function to the current Array element which is an Array
}
}
return sum; //To have the sum of the actual Array
}
var sumArr = [[[[[[[[[1]]]]]]]], 1];
console.log(arraySum(sumArr)); //now it returns 2
Try this :
function arraySum(arr) {
return arr.reduce(function(s, n) {
return s + ((n instanceof Array) ? arraySum(n) : +n || 0);
}, 0);
}
+n attempts to convert strings to integers, defaulting to zero if +n yields NaN.
http://jsfiddle.net/3z7pakfx/
Here is a solution that doesn't rely on iteration:
var arraySum = function(array) {
if (array.length === 0) {
return 0;
}
var rest = array.slice();
var next = rest.pop();
if (next instanceof Array) {
return arraySum(next) + arraySum(rest);
} else {
return next + arraySum(rest);
}
};
The sum of any value, v, and more values is -
If we do not have a value, v, return the empty sum, 0
By induction, we have a value, v. If the value is an array, return the sum of v plus the sum of more
By induction, we have a value v that is not an array. Return the numeric value of v plus the sum of more
const sum = ([ v, ...more ]) =>
v === undefined
? 0 // 1
: Array.isArray(v)
? sum(v) + sum(more) // 2
: Number(v) + sum(more) // 3
const result =
sum([[[[[[[[[1]]]]]]]], 1])
console.log(result)
// 2

Categories

Resources