Javascript map method on array of string elements - javascript

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

Related

pushing into an array inside an object using function it's returning Number instead of the value of pushed array [duplicate]

Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
I don't know if this has already been proposed or asked before; Google searches returned only a myriad number of questions related to the current functionality of Array.push().
Here's an example implementation of this functionality, feel free to correct it:
;(function() {
var _push = Array.prototype.push;
Array.prototype.push = function() {
return this[_push.apply(this, arguments) - 1];
}
}());
You would then be able to do something like this:
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray.push({}));
Where someFunction modifies the object passed in as the second parameter, for example. Now the contents of someArray are [{"someKey": "hello world"}].
Are there any drawbacks to this approach?
See my detailed answer here
TLDR;
You can get the return value of the mutated array, when you instead add an element using array.concat[].
concat is a way of "adding" or "joining" two arrays together. The awesome thing about this method, is that it has a return value of the resultant array, so it can be chained.
newArray = oldArray.concat[newItem];
This also allows you to chain functions together
updatedArray = oldArray.filter((item) => {
item.id !== updatedItem.id).concat[updatedItem]};
Where item = {id: someID, value: someUpdatedValue}
The main thing to notice is, that you need to pass an array to concat.
So make sure that you put your value to be "pushed" inside a couple of square brackets, and you're good to go.
This will give you the functionality you expected from push()
You can use the + operator to "add" two arrays together, or by passing the arrays to join as parameters to concat().
let arrayAB = arrayA + arrayB;
let arrayCD = concat(arrayC, arrayD);
Note that by using the concat method, you can take advantage of "chaining" commands before and after concat.
Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
Of course there is one: Other code will expect Array::push to behave as defined in the specification, i.e. to return the new length. And other developers will find your code incomprehensible if you did redefine builtin functions to behave unexpectedly.
At least choose a different name for the method.
You would then be able to do something like this: someFunction(value, someArray.push({}));
Uh, what? Yeah, my second point already strikes :-)
However, even if you didn't use push this does not get across what you want to do. The composition that you should express is "add an object which consist of a key and a value to an array". With a more functional style, let someFunction return this object, and you can write
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
return obj;
}
someArray.push(someFunction(value, {}));
Just as a historical note -- There was an older version of JavaScript -- JavaScript version 1.2 -- that handled a number of array functions quite differently.
In particular to this question, Array.push did return the item, not the length of the array.
That said, 1.2 has been not been used for decades now -- but some very old references might still refer to this behavior.
http://web.archive.org/web/20010408055419/developer.netscape.com/docs/manuals/communicator/jsguide/js1_2.htm
By the coming of ES6, it is recommended to extend array class in the proper way , then , override push method :
class XArray extends Array {
push() {
super.push(...arguments);
return (arguments.length === 1) ? arguments[0] : arguments;
}
}
//---- Application
let list = [1, 3, 7,5];
list = new XArray(...list);
console.log(
'Push one item : ',list.push(4)
);
console.log(
'Push multi-items :', list.push(-9, 2)
);
console.log(
'Check length :' , list.length
)
Method push() returns the last element added, which makes it very inconvenient when creating short functions/reducers. Also, push() - is a rather archaic stuff in JS. On ahother hand we have spread operator [...] which is faster and does what you needs: it exactly returns an array.
// to concat arrays
const a = [1,2,3];
const b = [...a, 4, 5];
console.log(b) // [1, 2, 3, 4, 5];
// to concat and get a length
const arrA = [1,2,3,4,5];
const arrB = [6,7,8];
console.log([0, ...arrA, ...arrB, 9].length); // 10
// to reduce
const arr = ["red", "green", "blue"];
const liArr = arr.reduce( (acc,cur) => [...acc, `<li style='color:${cur}'>${cur}</li>`],[]);
console.log(liArr);
//[ "<li style='color:red'>red</li>",
//"<li style='color:green'>green</li>",
//"<li style='color:blue'>blue</li>" ]
var arr = [];
var element = Math.random();
assert(element === arr[arr.push(element)-1]);
How about doing someArray[someArray.length]={} instead of someArray.push({})? The value of an assignment is the value being assigned.
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray[someArray.length]={});
console.log(someArray)

javascript findIndex callback arguments

I'm new to javascript.
I'm trying to find the index of a specific element in an array. I read about that I can use findIndex to loop through an array. But it seems that findIndex only accept three arguments: element, index and array. What if I want change the object that is used to be compared.
For example, I want for find the index of string 'b' in array ['a','b','c'],
var position = ['a','b','c'].findIndex(function(element, index, array){return element==='b'})
but how do I pass 'b' as parameters that I can change to callback function
Thanks
What about indexOf function? You just have to pass one argument, as searched element.
let arr = ['a','b','c'];
console.log(arr.indexOf('b'));
You can define the wanted character from the outside context inside the callback function:
var wantedChar = 'c';
var position = ['a','b','c'].findIndex(function(element, index, array){return element===wantedChar})
console.log(position);
By doing so, you can wrap all that up in a function:
var findPos = function(arr, char){
return arr.findIndex(function(element, index, array){return element===char});
}
console.log(findPos(['a','b','c'], 'c'));
Note: as already suggested, it makes more sense to use indexOf when just comparing strings. The findIndexfunction in combination with a custom callback is there for more sophisticated search, e.g. when dealing with complex structured objects.
function getPosition(){
var position = ["a","b","c"];
var a = position.indexOf("b");
document.getElementById("demo").innerHTML = a;
}
<button onclick="getPosition()">button</button>
<p id="demo"></p>

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

Check if an object has a key in javascript

I have two arrays of objects, and I want to filter the first one according to whats on the second one. Here's an example:
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
So in this case what I want to return is an array with the objects that have id's 23 and 54 of the first array, with all its possible properties (in this case, title).
Could you give me any hint that could help me?
Get a list of the indexes you want to search on using map:
var indexes = ary2.map(function (el) {
return el.id;
});
filter the results based on the list of indexes:
var result = ary1.filter(function (el) {
return indexes.indexOf(el.id) > -1;
});
DEMO
This might help you.
Loop through ary2, building up an array of each id value (let's call this array existingIds).
After that loop, now loop through ary1. For each item in ary1, check to see if the id value exists in the existingIds array that we just built up. If it does, append the current item to a result array.
I could write the code for you, but it will be a better learning experience if you first try this yourself :)
Might as well make use of some functional programming built into javascript.
filteredResults = ary1.filter(function(ele){
return (ary2.map(function(idobj){return idobj.id;}).indexOf(ele.id)>-1)
})
filter(function) will iterate through each element of an array, passing it through a callback function. From within that callback iff a true is returned, that value is kept. If false, that value is filtered out.
Also map(function) will iterate through each element of an array passing a callback value as well. All values returned from map callback will be injected into the result. So we can take the id from each element in ary2 and return it in the map function.
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
//Filter for the available ID's, store the resulting objects in a new array
filteredResults = ary1.filter(function(ele){
//map creates an array of just ID's
return (ary2.map(function(idobj){return idobj.id;}).indexOf(ele.id)>-1)
})
//now do whatever you were planning on doing with your results/
var res = document.getElementById("results");
filteredResults.forEach(function(ele){
res.innerHTML+="<li>{id:"+ele.id + ",title:" +ele.title+"}</li>"
})
console.log(filteredResults);
<ul id="results"></ul>
try this:
var ary1 = [{id: 23, title: 'blabla'},{id:43, title: 'bleble'}, {id:54, title:'blibli'}];
var ary2 = [{id:23},{id:54}, {id:65}];
var newary=[];
for(x in ary1){
for(y in ary2){
if(ary1[x].id == ary2[y].id){
newary.push(ary1[x]);
}
}
}
console.log(newary);// here newary will be your return newary;

Separating key value pairs into two variables with for loop

edit: don't do this. this was a stupid way of doing something I tried when I was new to programming
I have a list of 32 pieces of data in an array that are paired like this
"foo:bar","baz:example","cat:dog"
and I want to loop through that array to and stop on the pair that matches the user's input. So, for example, if the user types in "foo" it'll return both "foo" and "bar" separately, and if the user types in "bar" it'll return both "foo" and "bar". There are no values that repeat.
Right now what I have is a huge table with if statements. So if the user's input is x, then it returns the correct value. I had to do the matching by hand, and I'm assuming that looping through the array until the correct value is found would be more efficient than 64 different ifs.
I've tried something like this (just an example) using two separate arrays:
for (var i=0;i<array.length;i++) {
if (array[i] === user_input) {
var index = indexOf(array[i]);
break;
}
}
and then using the index variable as the index number of the value in each array, but it returns undefined
I've also tried this: Separate key and value pairs into two arrays
But it gives me all the values in the array, which I don't want. I just want one specific value that the user inputs. And while I can select one specific portion of the array using the index number, I can't figure out how to make that dynamic (e.g. changing based on what the user inputs).
Is it even possible to do this? And if not, what would be the best way?
Thanks.
You can do this:
function getPair(arr, search) {
var rtn = arr.filter(function (v, i) {
return new RegExp("\\b" + search + "\\b").test(v);
})[0];
return rtn ? rtn.split(':') : -1;
}
Use it like this:
var array = ["foo:bar","baz:example","cat:dog"];
getPair(array, "foo"); // ["foo","bar"]
Note: The above function returns -1 if the search string isn't found in the array.
Here's a function that iterates over the array, and checks if the user_input is anywhere. If so, it will return the string that it found a match for.
function getPair(array, user_input) {
for (var i=0;i<array.length;i++) {
var pair = array[i].split(':');
if (pair.indexOf(user_input) >= 0) {
return pair;
}
}
return [];
}
var array = ["foo:bar","baz:example","cat:dog"];
getPair(array, "foo"); //will return ['foo', 'bar']
getPair(array, "bar"); //will return ['foo', 'bar']
getPair(array, "dog"); //will return ['cat', 'dog']
getPair(array, "zzz"); //will return []
I would suggest to work with objects. First, convert your array:
var pair,obj1={},obj2={};
for (var i=0;i<array.length;i++) {
pair=array[i].split(":");
obj1[pair[0]]=pair[1];
obj2[pair[1]]=pair[0];
}
This will give you the following objects:
obj1={
"foo":"bar",
"baz":"example",
"cat":"dog"
};
obj2={
"bar":"foo",
"example":"baz",
"dog":"cat"
};
Then based on the user input:
if (obj1[user_input]) {return [user_input,obj1[user_input]];}
else if (obj2[user_input]) {return [obj2[user_input],user_input];}
else return undefined;
Live demo: http://jsfiddle.net/x23qG/

Categories

Resources