Return the index and array after reduced - javascript

I am playing with reduce method provided by mozilla. Underscore provides its own version which seems very similar. Reducing an array is very simple.
ArrayName.reduce(function(a,b) {
return a +b;
});
I use a very similar approach when sorting arrays as well. However, what I do not understand is how to return a list of calls. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce Provides a really cool table that shows how their method works. I set my array pretty much the same
var array = [1,2,3,100,55,88,2];
var sortArray= function(a,b) {
return a -b;
}
var sorted = array.sort(sortArray);
var reduced = sorted.reduce(function(previousValue,currentValue, index,array){
return previousValue + currentValue;
});
What I wanted to set up though was each call that was made. I figured that I could simply reference the index in the return value with a , at the end.
return previousValue + currentValue, index;
However, that only returns the index. I am trying to figure a way to get the value of each call. Does this approach allow you to get each call?

You don't need to use reduce for what you are doing. Try
function running_total(array) {
var sum = 0;
return array.map(function(elt) {
return sum += elt;
};
}
Reduce is about "boiling down" an array to a "single thing". In contrast, map is about "transforming" elements of the array. Your problem (as I understand it) is to transform each element of the array into the sum of itself and all the preceding elements. Therefore, conceptually, it's a map, not a reduce.

Using the , in the return statement will only return index due to the comma operator rule
[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array) {
console.log(previousValue+"--"+currentValue)
return previousValue + currentValue;
});
this will do want you want

You can create another array and store its value for each progress.
var array = [1,2,3,100,55,88,2];
var sortArray= function(a,b) {
return a -b;
}
var sorted = array.sort(sortArray);
var progress = [];
var reduced = sorted.reduce(function(previousValue,currentValue, index,array){
progress[index] = previousValue + currentValue;
return progress[index];
}, 0);
// ^^^^^
// give it a init value so it starts at first element.
console.log(progress);
However, as torazaburo says, as you expect to get an array, you should use .map which returns an array instead of .reduce.

Related

Using Map-Reduce to Return A Modified Array of Strings

I am learning map & reduce, but am having a hard time understanding how to utilize these methods to tackle problems.
For example,
Create a function that takes a number and returns an array of strings containing the number cut off at each digit.
420 should return ["4", "42", "420"]
My old Approach:
function createArrayOfTiers(num) {
var numArr = num.toString().split('');
var output = [];
for(var i = numArr.length-1; i>=0; i--) {
output.unshift(numArr.join('');
numArr.pop();
}
return output;
}
Attempt to use map-reduce combination:
function createArrayOfTiers(num) {
var numArr = num.toString().split('');
return numArr.map(function(element) {
var newElement = numArr.reduce(function(acc, val) {
return acc + val;
});
numArr.splice(element, 1);
return newElement;
});
}
You have used two loops, but apparently it can be done just with one.
function n(num) {
let res = (""+num).split('').map((_,i) => (""+num).slice(0, i+1));
return res;
}
console.log(n(420));
console.log(n(13579));
One-liner.
const n = num => (""+num).split('').map((_,i) => (""+num).slice(0, i+1));
console.log(n(420));
console.log(n(13579));
As others noted, that this problem doesn't seem to be the best use case of the map and reduce functions.
map function provides the element, index and array information in the parameters. Making use of these you can iterate on the elements you need to apply the reduce function.
Statement var arrayToIterate = arr.slice(0,i+1); helps to achieve the above mentioned array to iterate.
Complete Code:
function createArrayOfTiers(num) {
var numArr = num.toString().split('');
return numArr.map(function(element, i, arr) {
var arrayToIterate = arr.slice(0,i+1);
var newElement = arrayToIterate.reduce(function(acc, val) {
return acc + val;
},"");
return newElement;
});
}
var result = createArrayOfTiers(420);
console.log(result);
I don't think these are good uses-cases of map or reduce, but here goes :
var numArr = [4,2,0];
var result = numArr.map(e => numArr.join('')) // now ["420", "420", "420"]
.map((arr, i) => arr.substring(0, i+1)) // now ["4", "42", "420"]
console.log(result);
We first replace every element of the array by the whole (unmodified) array joined into a string, then substring each of these strings based on their position in the outer array.
There's a reduction hidden in there, although not using reduce : join reduces [4, 2, 0] to "420".
I am learning map & reduce, but am having a hard time understanding how to utilize these methods to tackle problems.
Mapping associates to each value of the source array a new value provided by a mapping function : if you have an [x, y, z] array, a mapping function f(x)=x+1, the result of mapping the array with the function will be [x+1, y+1, z+1].
I believe reduction was meant to "reduce" an array to a primitive type, although I might be mistaken. If you have an [x, y, z] array and reduce it with the addition operation, the result will be x+y+z.

How to use lodash _.find to return value even if iterating over numbers

so I have this function:
var res = _.find(table_campaign_boards().getAllPrimaryKeys(), (campaign_board_id,v) => {
var recCampaignTimeline = table_campaign_boards().getRec(campaign_board_id);
if (recCampaignTimeline.campaign_id == i_campaign_id) {
var board_id = recCampaignTimeline['board_id']
return table_boards().getRec(board_id);
}
});
And when a match is found, I get back the index since table_campaign_boards().getAllPrimaryKeys returns a list of numbers. How do I have _.find, find and stop on first value, and return the object found and not the index it found. Sure I can use for loop and break, but would rather use lodash as I get both key / value.
Thanks,
Sean

Javascript map method on array of string elements

I am trying to understand how to implement the map method (rather than using a for loop) to check a string for palindromes and return boolean values for whether the mapped array elements reversed are the same as the original array elements. I cannot seem to understand the syntax of the map method. How do I get the map to function on each element in the original array? What is the value? Here is my working code, which is only logging a value of undefined:
function palindromeChecker(string) {
var myString = string.toLowerCase();
var myArray = myString.split(" ");
var newArray = myArray.map(function (item) {
item.split("").reverse().join("");
return newArray === myArray;
});
}
console.log(palindromeChecker("What pop did dad Drink today"));
Here is a link to the fiddle:
https://jsfiddle.net/minditorrey/3s6uqxrh/1/
There is one related question here:
Javascript array map method callback parameters
but it doesn't answer my confusion about the syntax of the map method when using it to perform a function on an array of strings.
The map method will literally 'map' a function call onto each element in the array, take this as a simple example of increasing the value of each integer in an array by 1:
var items = [1,2,3];
items.map(function(item) {
return item + 1;
});
// returns [2,3,4]
In your case, you are trying to use map to accept or reject a string if it's a palindrome, so a simple implementation might be:
var items = ['mum', 'dad', 'brother'];
items.map(function(item) {
return item.split('').reverse().join('') === item;
});
// returns [true, true, false]
I'm not 100% sure of your reasons for using map, because if you were trying to just filter the array and remove the strings that aren't palindromes, you should probably use the filter method instead, which works in the same way, but would remove any that return false:
var items = ['mum', 'dad', 'brother'];
items.filter(function(item) {
return item.split('').reverse().join('') === item;
});
// returns ['mum', dad']
In your case you are splitting a string first to get your array of characters; you may also want to make that string lower case and remove punctuation, so an implementation might be:
var string = 'I live at home with my Mum, my Dad and my Brother!';
var items = string.toLowerCase().replace(/[^a-z0-9-\s]+/, '').split(' ');
items.filter(function(item) {
return item.split('').reverse().join('') === item;
});
// returns ['i', 'mum', dad']
As mentioned in one of the comments on your question, you need to ensure you return a value from your function if you are using a separate function to perform the check, so this is how your function should look:
function checkPalindromes(string) {
var items = string.toLowerCase().replace(/[^a-z0-9-\s]+/, '').split(' ');
items.filter(function(item) {
return item.split('').reverse().join('') === item;
});
return items;
}
And you would call it using:
checkPalindromes('I live at home with my Mum, my Dad and my Brother!'); // ['i', 'mum', 'dad']
try something like this:
let str = 'hello';
let tab = [...str];
tab.map((x)=> {
console.log("|"+x+"|");
return x;
})
newArray should include reversed version of theall items in myArray. After that, newArray should be reversed and joined with space in order to get the reversed version of the input string.
Here is the code:
function palindromeChecker(string) {
var myString = string.toLowerCase();
var myArray = myString.split(" ");
var newArray = myArray.map(function (item) {
return item.split("").reverse().join("");
});
console.log(newArray);
return newArray.reverse().join(" ") === string;
}
console.log(palindromeChecker("dad did what"));
Javascript map method on array of string elements by using split() function.
let str = 'hello';
str.split('').map((x)=> {
console.log("|"+x+"|");
return x;
})
Map is a higher-order function available in ES5. I think your newArraywill contain an array of boolean values.
In essence, map will iterate over every value in your array and apply the function. The return value will be the new value in the array. You can also use map and save the information you need somewhere else, and ignore the result of course.
var arr = [1,2,3,4];
var newArray = arr.map(function(i) {
return i * 2;
});
//newArray = [2,4,6,8]
The map function in javascript (and pretty much in any language) is a great little function that allows you to call a function on each of the items on a list, and thus changing the list itself.
The (anonymous) function you're passing as an argument accepts an argument itself, which is filled by an item of the list it is working on, each time it is called.
So for a list [1,2,3,4], the function
function(item) { return item + 1 }, would give you a list of [2,3,4,5] for a result. The function you passed to $.map() is run over each element of the list, and thus changing the list.
So for your code: in the function you're passing as an argument to $.map(), you're returning whether the old and new array are equal (which is false btw). So since you're returning a boolean value, the list you'll end up with is a list of bools.
What I think you want to do, is extract the newArray == myArray from the function you're passing to $.map(), and putting it after your $.map() call.
Then inside the function you're passing to $.map(), return the item you're splitting and whatnot, so your newArray will be an array of strings like myArray.
Apart from a few minor mistakes in your code, such as scope issues (you're referencing the "newArray" and "myArray" outside of the function in which they where defined, and therefore, getting "undefined")..
The main issue you had is that you addressed the ENTIRE array inside the map function, while the whole concept is breaking things down to single elements (and then the function collects everything back to an array for you).
I've used the "filter" function in my example, because it works in a similar manner and I felt that it does what you wanted, but you can change the "filter" to a "map" and see what happends.
Cheers :)
HTML:
<body>
<p id="bla">
BLA
</p>
<p id="bla2">
BLA2
</p>
</body>
Javascript:
function palindromeChecker(string) {
var myString = string.toLowerCase();
var myArray = myString.split(" ");
var newArray = myArray.filter(function (item) {
var reversedItem = item.split('').reverse().join('');
return item == reversedItem;
});
document.getElementById("bla").innerHTML = myArray;
document.getElementById("bla2").innerHTML = newArray;
}
palindromeChecker("What pop did dad Drink today");
Thanks for your input, all. This is the code I ended up with. I fixed the scope issues in the original post. My main problem was understanding the syntax of the map method. In particular, I could not understand from other online resources how to determine the value in the callback function. So, with much help from above I have placed the map method inside the palindromeChecker, and done all of the work on the array inside the map function.
var palindromeChecker = function(string) {
var newString = string.toLowerCase().split(' ');
newString.map(function(item) {
console.log(item.split('').reverse().join('') === item);
});
};
palindromeChecker("What pop did dad drink today");
//Returns false, true, true, true, false, false

How can I implement the lodash _.remove function in modern browsers?

I have this code using lodash:
_.remove(this.home.modal.data.subTopics, function (currentObject) {
return currentObject.subTopicId === subTopicToDelete;
});
Can someone give me advice as to how I could do the same using modern browser functions without lodash?
Note it would be okay for the output of the remove to go into another variable.
You could use Array#filter() and negate the filter clause:
this.home.modal.data.subTopics.filter(function (currentObject) {
return currentObject.subTopicId !== subTopicToDelete;
});
This will return an array where subTopicId does not equal subTopicToDelete. It's then up to you to save it in a variable or wherever.
Or, if you want to create a method out of it, you could do:
function remove(array, filterMethod) {
return array.filter(function(){
return !filterMethod.apply(this, arguments);
});
}
Why not have a look at lodash's source code for _.remove?
function remove(array, predicate, thisArg) {
var index = -1,
length = array ? array.length : 0,
result = [];
predicate = getCallback(predicate, thisArg, 3);
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result.push(value);
splice.call(array, index--, 1);
length--;
}
}
return result;
}
(The getCallback call is not really interesting here, just replace it with a predicate function that returns a boolean value for the given arguments: value, index, array. Not all of them need to be supplied obviously, this is JavaScript after all!)
Lodash uses Array.prototype.splice at the appropriate position, pushing the removed element onto the result array. Then it decreases the current loop index and the saved length by 1 using --, because every time you use .splice, you modify the array directly, for instance:
var arr = ['a', 'b'];
arr.splice(0, 1);
arr[1] // undefined
splice in this context really just the same as Array.prototype.splice. You can as well do array.splice(index--, 1).
A maybe more simple/understandable way is to (for-)loop through the array from the right, starting at array.length - 1 and ending at 0. Then splice every element at the current index, if it passes the predicate function, and push the result value of that operation onto the result array. Return the result array after the loop.
This works the same, because if you start removing elements from the right side, the index of the rest of the looped elements doesn't change. Maybe there are performance advantages to lo-dash's code, but I couldn't tell you that.
You could adapt Array.prototype to suit your needs. Some people don't like this approach, but it can be useful sometimes. In this example I pass in the key and the value I want to amend the array by:
if (!Array.prototype.remove) {
Array.prototype.remove = function (key, value) {
return this.filter(function (el) {
return el[key] !== value;
});
}
}
data.remove('name', 'dan');
DEMO

Delete the array items which have lower specific value

I want to let array1 transform to array2.
The keyword is the test,test2,885,length.I want the keyword's next value(#?) to the next # is the highest.
var array1=["4#test#4#T#limited","6#test#6#885#restricted","7#test2#2#2#limited","8#test2#4#3#limited","11#885#1#TT#restricted","15#length#1#taw#restricted","17#885#11#T#limited"];
var arrar2=["6#test#6#885#restricted","8#test2#4#3#limited","17#885#11#T#limited","15#length#1#taw#restricted"];
Is this what you want?
var array1=["4#test#4#T#limited","6#test#6#885#restricted","7#test2#2#2#limited","8#test2#4#3#limited","11#885#1#TT#restricted","15#length#1#taw#restricted","17#885#11#T#limited"];
var keywords = ["test","test2","885","length"];
var array2 = [];
keywords.forEach(function (key) {
var matched = [];
var regex = new RegExp("\\b" + key + "#(\\d+)");
array1.forEach(function (value) {
if (regex.test(value)) {
matched.push([parseInt(RegExp.$1), value]);
}
});
if (matched.length > 0) {
matched.sort(function (a, b) {
return b[0] - a[0];
});
array2.push(matched[0][1]);
}
});
alert(array2);
JsFiddle example
You can use underscorejs to filter.
http://underscorejs.org/#filter
Then you can use javascript Array's sort method to sort the array if needed. You can pass a custom sorting function to sort. http://www.w3schools.com/jsref/jsref_sort.asp
The simplest way to "delete items from an array" based on the items fulfilling a condition is to use Array.prototype.filter (with the condition reversed).
In your case, it's rather hard to do because of how you organized your data (bundling it all in a string makes it hard to work with). Here is how i would work around it, but feel free to structure your data better from the start to avoid the awkward conversions:
var array1=["4#test#4#T#limited","6#test#6#885#restricted","7#test2#2#2#limited","8#test2#4#3#limited","11#885#1#TT#restricted","15#length#1#taw#restricted","17#885#11#T#limited"];
Make the data easier to work with by extracting the keyword and the value (i also keep some information to return to the original shape of the array):
var saneData = array1.map(function(item, index){
var split = item.split('#');
return {
keyword : split[1],
value: +split[0],
original : item,
originalIndex : index
}
});
Sort the data by the keyword (so all items with the same keywords go next to each other) and by the values (so the biggest value is first in a subset with the same keywords):
saneData.sort(function(a,b){
if (a.keyword !== b.keyword) {
return a.keyword.localeCompare(b.keyword);
} else {
return b.value - a.value;
}
});
Filter the array, keeping just the first item in a subset with the same keyword:
var filteredData = saneData.filter(function(item, index) {
if (index === 0) return true; // first item is good
return item.keyword !== saneData[index-1].keyword;
});
Return to the original form of the array (with the order preserved):
var array2 = filteredData.sort(function(a,b){ return a.originalIndex - b.originalIndex; }).map(function(item){ return item.original; });
// Result: ["6#test#6#885#restricted", "8#test2#4#3#limited", "15#length#1#taw#restricted", "17#885#11#T#limited"]

Categories

Resources