How to use reduce() method on for loops? - javascript

I am trying to write a code that converts a Binary into string, i take solutions step by step, my first step is add charcodes then use fromCharcode, I don't know if this is possible but on this is my code:
function binaryAgent(str) {
var x = str.split(' ').map(function (item) { // split with space
return item.split(''); //split every character
});
var fg = [];
for(var i=0; i<x.length; i++) {
var f = x[i].reduce(function (toArray,item){
debugger;
var rightPattern = [128,64,32,16,8,4,2,1]; // i want to create this array on every iteration
var op = rightPattern.shift(); // on every iteration, shift a value from rightPattern, this is for binary pattern
if(item=='1'){ // if item is 1,i think it doesn't matter if it's string or num, I care for 0 and 1 only, push the variable op, shifted from array
return toArray.push(op); // push it on the initial value,
}
}, []); // []<-- initial array.
return x;
}
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
I checked this with debugger and I have observed that: ON every iteration, my rightPattern array is set to undefined again and reset, I also cannot use push and I have this error, TypeError: Cannot read property 'push' of undefined
on MDN, there is an example using concat() method so i tried to push Array.prototype.reduce()

I'd write your function like this:
function binaryAgent(encoded) {
return encoded.split(' ').map(function(bytestr) {
return String.fromCharCode(parseInt(bytestr, 2));
}).join('');
}
Converting binary representation into numbers is, well, an old task, and it's already solved for you. Even if you want to write your own implementation for studying purposes, it's better to abstract it (so that you can replace parseInt(bytestr, 2) line - but leave the rest of the code intact.
One possible reduce-using approach (not the most performant, mind you, but employing a pretty common technique):
function parseBinary(str) {
return str.split('').reduce(function(acc, el) {
return acc * 2 + +el;
}, 0);
}
That is, you don't have any 'pre-filled' arrays of powers of 2; instead your accumulator is multiplied by 2 at each reducer step, adding the current digit. As + operator is overloaded, you should convert the digit operand into a number (the easiest way is applying unary plus - +).
Answering the question given in the comments: you can easily convert any number to binary, octal or hex format by calling toString() on it, with a passed argument treated as a radix. But here's a function for it:
function toBinary(num, reslen) {
var res = '';
while (num || res.length < reslen) {
res = (num & 1) + res;
num >>= 1;
}
return res;
}

first of all - in your reduce function - if item wont be equal to one - in the next iteration toArray will be undefined.
you need to always return a value in the reduce function in order for the first argument (the accumulator) to be defined
should be something like that -
if (item == 1) {
toArray.push(op);
}
return toArray;
other than that as I understand your code - the rightPattern var should be outside the reduce function but inside the for loop.

Related

javscript recursion string reverse

I tried to find a recursive solution on my own to reverse a string s but it returns 'undefined' for strings >1 char.
Can somebody please help me to debug this?
I know it is not the elegant way but finding the error could help me advancing.
Thank U very much!
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
revFunc(s, r, n, i);
};
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
return revFunc(s, r, n, i);
};
Not a good fit for recursion
While the minor correction already presented fixes your function, I want to suggest that this version shows a misunderstanding about recursion.
Your function is using recursion to update what would otherwise be local variables in a while loop. It could be rewritten like this:
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
while (i <= n) {
r = r + s[n - i]
i++
}
return r
};
console .log (reverse ('abcde'))
The recursion you use is just another means of writing that same code.
Recursion is meant for something a bit different. We want our algorithms to match our data structures. For recursion to really be meaningful, we should should use it on a recursive data structure.
But we can do so for this problem.
Thinking of a string recursively
There are often many different ways to think of a single data structure. We can think of a string as a recursive structure this way:
A string is either
The empty string, "", or
a character followed by a string
We can call the two parts of a non-empty string the head and the tail.
Using the recursive definition in a recursive algorithm
With that formulation, we can write a recursive algorithm that matches the structure:
The reversal of a string is either
The reversal of the empty string (which is still the empty string), or
The reversal of tail, followed by the head
Then the code practically writes itself:
const reverse = (string) =>
string .length == 0
? ""
: reverse (string .slice (1)) + string[0]
console .log (reverse ('abcdefg'))
Variants
There are certainly variations of this possible. We could want to be ready for when tail-call-optimization is finally common in JS environments, and could change this to a tail-recursive version, something like
const reverse = (string, result = "") =>
string .length == 0
? result
: reverse (string .slice (1), string [0] + result)
(Note that there is a potential problem with this style. Default parameters can get in the way of using the function in certain contexts. You cannot, for instance, successfully call strings .map (reverse) with this version. You could do this by splitting it into a helper function and a main function, but that's taking us afield.)
Or, taking advantage of the fact that strings are iterables, we could write a nicely simple version using parameter destructuring along with a default value:
const reverse = ([head = undefined, ...tail]) =>
head == undefined
? ""
: reverse (tail) + head
The advantages of recursion
And it's hard to imagine getting much simpler than that. This version captures the algorithm quite directly. And the algorithm is cleanly tied to our description of the data structure.
Note one thing that none of these functions use: local variables. Simple recursion can often be written in such a way that there is no need for them. This is a major blessing, because that means there is no place for mutable state to hide. And mutable state is the source of many, many programming errors.
You forgot to return
return revFunc(s, r, n, i);
Updated:
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
return revFunc(s, r, n, i);
};
Suggestion: Please use better name for variables, it sucks s,r,n,i
Can you try a simple solution :
let str = "hello";
let reverse_str = str.split("").reverse().join("");

How do I assign my .reduce function output to a variable?

Given an object and a key, getElementsThatEqual10AtProperty returns an array containing all the elements of the array located at the given key that are equal to ten.
I want to assign what my .reduce method outputs to a variable then use that variable inside my if statement. My code evaluates to NaN.
function getElementsThatEqual10AtProperty(obj, key) {
var arrayTotal = 0;
obj[key].reduce(function(a,b){
arrayTotal = a + b;
});
if(arrayTotal === 10) {
return obj[key];
}
};
You're approaching reduce incorrectly. You're almost using it like Array#forEach. Remember that callbacks are functions. They expect to return an actual value.
When you read the docs, you'll see that reduce also needs an accumulator, that is an argument after the callback.
const sum = obj[key].reduce(function(a,b){
return a + b
}, 0)
Or if you want the newer and prettier version:
const sum = obj[key].reduce((a,b) => a + b, 0)
When you have a one liner, return is implicit, which means it's implied, as opposed to explicit.
The accumulator is what your value starts at while it totals up the values.
Array.reduce(callback, accumulator)

Making a Addition function using Javascript - toString(), parseInt(), etc

I'm a new student who's learning Javascript for the first time. This time I'm trying to better grasp the concepts of converting numbers into strings, storing them in arrays, converting them back to numbers, and adding.
In this assignment, I'm trying to write a function that takes the individual digits of a number and adds them together.
So for example, the function would take (95) and return 14. Or given (135), would return 9.
Here's what I got so far:
var addDigits = function(num) {
var newNum = num.toString();
newNum = newNum.split('');
var sum = 0;
var thirdNum = newNum.forEach(function(x) {
parseInt(x);
sum + x };
};
I'm fully aware that is not very good code, but could anyone give me any tips? Should I be using parseInt or Number?
You're pretty close. Few things though. array.forEach doesn't return anything. It's used for creating side effects (increasing sum would be considered a side effect of the function you're passing into the forEach). So setting the forEach to a variable doesn't accomplish anything. parseInt does return something, so you need to set it to a variable. And you also want to increase sum by the parsed integer plus the sum you already have. You can look into the += operator for that if you wish. Last, you need to return a value from the function itself! As it is, if you did var added = addDigits(123), added would be undefined. So finish it off with a return statement.
After you've got the grasp of that, I'd suggest looking into array.reduce to replace array.forEach since it's perfect for a problem such as this.
var addDigits = function(string) {
newNum = string.split('');
var sum = 0;
for(var i = 0 ; i < newNum.length ; i++) sum += parseInt(newNum[i]);
return sum;
};
console.log(addDigits("1234"));
Maybe this will be better:
function getDigitsSum(number) {
var charArray = (number + '').split('');
var sum = 0;
charArray.forEach(function(item) {
sum += parseInt(item)
})
return sum;
}
Number() performs type conversion, whereas parseInt() performs parsing.
What is the difference between parseInt() and Number()?
In this situation, it doesn't make a difference since the strings are proper integers.
Here's how I would do it.
var addDigits = function(num) {
var newNum = num.toString().split('');
var sum = newNum.map(Number).reduce((prev, curr) => prev + curr);
return sum;
};
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Assuming your input will always be an integer string, consider the following function:
var addDigits = function(strInt) {
var int = function(x) {
return parseInt(x,10) //10 is the radix
}
return strInt.split('').map(int).reduce(function(a,b){return a+b});
}
The function tied to var int will ensure that the provided integer string be parsed into its corresponding base 10 integer (notice the difference in type, which can be validated with Javascript's built-in typeof() function). The return will first .split the string, .map the int function against every value within the given string, and then apply whatever function you have within .reduce against an accumulated value - in this case, simply adding against each member of the array.

Using extra callback parameters to Array.prototype.some

Do you have any real-world example of the use of the second and third parameters for the callback to Array.prototype.some or Array.prototype.any?
According to MDN:
callback is invoked with three arguments: the value of the element, the index of the
element, and the Array object being traversed.
I've personally never used them.
I have been working for some time on the Javascript functional programming library, Ramda, and early on we made the controversial decision not to use the index and array parameters for other similar functions that we created. There are good reasons for this, which I don't need to get into here, except to say that for some functions, such as map and filter, we find such extra parameters do have some occasional utility. So we offer a second function which supplies them to your callback. (For example, map.idx(yourFunc, list).)
But I've never even considered doing so for some or every. I never imagined a practical use of these. But there is now a suggestion that we include these functions in our list of index-supporting ones.
So my question again is whether you have ever found an actual, live, real-world callback function to some or every which actually needs these parameters? If so, could you describe it?
Answers of "No, I never do," would be helpful data too, thanks.
Quick search in our code:
function isAscending(array) {
return array.every(function (e, idx, arr) {
return (idx === 0) ? true : arr[idx-1] <= e;
});
}
I could imagine something like the following code to check whether an array is duplicate-free:
….every(function(v, i, arr) {
return arr.indexOf(v, i+1) == -1;
})
Where … is a complex expression so that you'd really have to use the arr parameter - which is no more an issue if you'd properly factor out the functionality in an own function that takes the array as an argument.
The second parameter can be useful sometimes, but I support your position that it is rather seldom used.
Yes, they are helpful
These extra parameters actually do come in handy, but not that often.
In the recent past, I had written a function to find all the permutations of a list of elements:
permute :: [a] -> [[a]]
For example permute [1,2,3] would be:
[ [1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
, [3,2,1]
]
The implementation of this function is quite simple:
If the input is [] then return [[]]. This is the edge case.
If the input is say [1,2,3]:
Add 1 to every permutation of [2,3].
Add 2 to every permutation of [1,3].
Add 3 to every permutation of [1,2].
Of course, the function is recursive. In JavaScript, I implemented it as follows:
var permute = (function () {
return permute;
function permute(list) {
if (list.length === 0) return [[]]; // edge case
else return list.reduce(permutate, []); // list of permutations
// is initially empty
}
function permutate(permutations, item, index, list) {
var before = list.slice(0, index); // all the items before "item"
var after = list.slice(index + 1); // all the items after "item"
var rest = before.concat(after); // all the items beside "item"
var perms = permute(rest); // permutations of rest
// add item to the beginning of each permutation
// the second argument of "map" is the "context"
// (i.e. the "this" parameter of the callback)
var newPerms = perms.map(concat, [item]);
return permutations.concat(newPerms); // update the list of permutations
}
function concat(list) {
return this.concat(list);
}
}());
As you can see, I have used both the index and the list parameters of the permutate function. So, yes there are cases where these extra parameters are indeed helpful.
However, they are also problematic
However these superfluous arguments can sometimes be problematic and difficult to debug. The most common example of this problematic behavior is when map and parseInt are used together: javascript - Array#map and parseInt
alert(["1","2","3"].map(parseInt));
As you can see it produces the unexpected output [1,NaN,NaN]. The reason this happens it because the map function calls parseInt with 3 arguments (item, index and array):
parseInt("1", 0, ["1","2","3"]) // 1
parseInt("2", 1, ["1","2","3"]) // NaN
parseInt("3", 2, ["1","2","3"]) // NaN
However, the parseInt function takes 2 arguments (string and radix):
First case, radix is 0 which is false. Hence default radix 10 is taken, resulting in 1.
Second case, radix is 1. There is no base 1 numeral system. Hence we get NaN.
Third case, radix is 2 which is valid. However there's no 3 in base 2. Hence we get NaN.
As you see, superfluous arguments can cause a lot of problems which are difficult to debug.
But, there is an alternative
So these extra arguments are helpful but they can cause a lot of problems. Fortunately, there is an easy solution to this problem.
In Haskell if you want to map over a list of values and the indices of each value then you use do it as follows:
map f (zip list [0..])
list :: [Foo]
[0..] :: [Int]
zip list [0..] :: [(Foo, Int)]
f :: (Foo, Int) -> Bar
map f (zip list [0..]) :: [Bar]
You could do the same thing in JavaScript as follows:
function Maybe() {}
var Nothing = new Maybe;
Just.prototype = new Maybe;
function Just(a) {
this.fromJust = a;
}
function iterator(f, xs) {
var index = 0, length = xs.length;
return function () {
if (index < length) {
var x = xs[index];
var a = f(x, index++, xs);
return new Just(a);
} else return Nothing;
};
}
We use a different map function:
function map(f, a) {
var b = [];
if (typeof a === "function") { // iterator
for (var x = a(); x !== Nothing; x = a()) {
var y = f(x.fromJust);
b.push(y);
}
} else { // array
for (var i = 0, l = a.length; i < l; i++) {
var y = f(a[i]);
b.push(y);
}
}
return x;
}
Finally:
function decorateIndices(array) {
return iterator(function (item, index, array) {
return [item, index];
}, array);
}
var xs = [1,2,3];
var ys = map(function (a) {
var item = a[0];
var index = a[1];
return item + index;
}, decorateIndices(xs));
alert(ys); // 1,3,5
Similarly you can create decorateArray and decorateIndicesArray functions:
function decorateArray(array) {
return iterator(function (item, index, array) {
return [item, array];
}, array);
}
function decorateIndicesArray(array) {
return iterator(function (item, index, array) {
return [item, index, array];
}, array);
}
Currently in Ramda you have two separate functions map and map.idx. The above solution allows you to replace map.idx with idx such that:
var idx = decorateIndices;
var arr = decorateArray;
var idxArr = decorateIndicesArray;
map.idx(f, list) === map(f, idx(list))
This will allow you to get rid of a whole bunch of .idx functions, and variants.
To curry or not to curry
There is still one small problem to solve. This looks ugly:
var ys = map(function (a) {
var item = a[0];
var index = a[1];
return item + index;
}, decorateIndices(xs));
It would be nicer to be able to write it like this instead:
var ys = map(function (item, index) {
return item + index;
}, decorateIndices(xs));
However we removed superfluous arguments because they caused problems. Why should we add them back in? Two reasons:
It looks cleaner.
Sometimes you have a function written by somebody else which expects these extra arguments.
In Haskell you can use the uncurry function to solve this problem:
map (uncurry f) (zip list [0..])
list :: [Foo]
[0..] :: [Int]
zip list [0..] :: [(Foo, Int)]
f :: Foo -> Int -> Bar
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f :: (Foo, Int) -> Bar
map (uncurry f) (zip list [0..]) :: [Bar]
In JavaScript the uncurry function is simply apply. It is implemented as follows:
function uncurry(f, context) {
if (arguments.length < 2) context = null;
return function (args) {
return f.apply(context, args);
};
}
Using uncurry we can write the above example as:
var ys = map(uncurry(function (item, index) {
return item + index;
}), decorateIndices(xs));
This code is awesome because:
Each function does only one job. Functions can be combined to do more complex work.
Everything is explicit, which is a good thing according to the Zen of Python.
There's no redundancy. There's only one map function, etc.
So I really hope this answer helps.

Recursion with names

I'm a little lost in general, but if someone could please briefly explain why this code works that would be great!
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Capitalize function
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
// Our recursive function
function fixLetterCase(array, i) {
// Base case
if (i === array.length) {
return;
}
// Action
array[i] = capitalize(array[i]);
// Recursive case
return fixLetterCase(array, i + 1);
}
// Here is our function call
fixLetterCase(capitals, 0);
console.log(capitals);
While I understand this is not an answer to the question, I thought it might help to see a non-recursive version of the logic:
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Simple function to capitalize word
function fixLetterCase(array) {
for(var i = 0; i < array.length; i++) {
array[i] = array[i].charAt(0).toUpperCase() + array[i].slice(1).toLowerCase();
}
}
fixLetterCase(capitals);
console.log(capitals);​
Here's a working fiddle to play with.
function fixLetterCase(array, i) {
// At some point, this is true, so the algorithm stops
if (i === array.length) { return; }
// At this point, the function did not returned. The function logic continues.
// Replace the array key with a new value = the return value of captialize()
array[i] = capitalize(array[i]);
// i increments by one, and the function itself is called again.
return fixLetterCase(array, i + 1);
}
// Initialize the function, with starting offset ("counter") i=0
fixLetterCase(capitals, 0);
// Our recursive function
function fixLetterCase(array) {
for (var i = 0, length = array.length; i < length; i++) {
array[i] = capitalize(array[i]);
}
}
Would probably be a better, more readable, more performant solution. This case does not need recursion at all, a loop should be more effective. You don't need that many function calls and you don't need to evaluate the array's length with every function call.
I assume you're talking about the recursive part. It's really just an exotic way to iterate over the array.
Conventionally you might do this with a for loop, following the pattern (forgive the totally weird pseudo-code, my own gross invention):
for ([initialization]; [condition]; [modification])
[function]
With recursion you can do it as:
[function [initialization]]
if [!condition]
break
[function [modification]]
I personally feel there's not much benefit to the recursive version in this case, as it's much less idiomatic and thus less obvious how it works; and it offers no performance benefit.
The function fixLetterCase is called with i equal to zero. When fixLetterCase runs for the first time, it calls capitalize on the first word in the array. In the recursive call, it increments i with 1 so that means it will capitalize the next word in the array. It will keep doing this until it reaches the end of the array.
That's why the function works: the index of the word that needs to be capitalized is incremented each time and in the last call, when the index is equal to the length of the array, the 'recursion' ends.
Note that this is not a typical use of recursion because there's nothing returned from the recursive calls. Also note that this could be written much more straightforwardly as a for loop.
This really doesn't need to be written recursivly, you could do the same thing with
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Capitalize function
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
// Our recursive function
function fixLetterCase(array, i) {
// Action
array[i] = capitalize(array[i]);
}
// Here is our function call
for(var i = 0; i < capitals.length; i++)
{
fixLetterCase(capitals, i);
}
console.log(capitals);
The recursive part is only iterating through the capital words and escapes when you reach the end of the array. Hopefully reading it like this will make it more clear.

Categories