I'm trying to write a function that will capitalize the first letter of the first and last name only... any ideas on how to approach this?
const namesHardest = ['emIly sMith', 'angeliNA Jolie', 'braD piTt'];
function capitalizeNames(peopleArray) {
return peopleArray.toString().toLowerCase().split('').map(function(word) {
return (word.charAt(0).toUpperCase() + word.slice(1));
}).join(' ').split();
}
// set the resulting array to this variabble
const capitalizedNames = capitalizeNames(namesHardest);
capitalizedNames;
One issue is using array.toString - that results in a string like
'emIly sMith angeliNA Jolie braD piTt'
so, you've lost your array elements
You need to work on each element individually, by using array.map
function capitalizeNames(peopleArray) {
return peopleArray.map(function(name) {
/* do something with each name *
})
}
Your other issue is that split('') splits a string into characters - but you want to split it on spaces ... i.e. split(' ')
So now, we have
function capitalizeNames(peopleArray) {
return peopleArray.map(function(name) {
return name.split(' ').map(function(word) {
/* do something with each part of name *
});
});
}
so, now, how to capitalise a string - your code works, but I prefer
word[0].toUpperCase() + word.slice(1).toLowerCase();
put it together and you get
function capitalizeNames(peopleArray) {
return peopleArray.map(function(name) {
return name.split(' ').map(function(word) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
});
});
}
or, in ES2015+, using arrow functions (since your code uses const, why not use all of ES2015+)
const namesHardest = ['emIly sMith', 'angeliNA Jolie', 'braD piTt'];
const capitalizeNames = peopleArray => peopleArray.map(name =>
name.split(' ').map(word =>
word[0].toUpperCase() + word.slice(1).toLowerCase()
).join(' ')
);
const capitalizedNames = capitalizeNames(namesHardest);
console.log(capitalizedNames);
Sorry I am late to party, I'd rather use array.from with closure
const namesHardest = ['emIly jack sMith', 'angeliNA Jolie', 'braD piTt'];
let conv=Array.from(namesHardest,a=>a.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
}))
console.log(conv);
let namesHardest = ['emIly sMith', 'angeliNA Jolie', 'braD piTt'];
namesHardest = namesHardest.map(val => {
let [first, last] = val.toLowerCase().split(' ');
first = first.replace(first[0], first[0].toUpperCase());
last = last.replace(last[0], last[0].toUpperCase());
return `${first} ${last}`
});
console.log(namesHardest);
Your logic is a bit off. First, for each string, you need to split it by spaces to get the first and last name. Then, you can upcase the first character of each string. See below:
const namesHardest = ['emIly sMith', 'angeliNA Jolie', 'braD piTt'];
const capitalizeName = (name) => `${name[0].toUpperCase()}${name.slice(1)}`;
const capitalizeNames = (peopleArray) => peopleArray.map(name => {
const [first, last] = name.toLowerCase().split(' ');
return `${capitalizeName(first)} ${capitalizeName(last)}`;
});
console.log(capitalizeNames(namesHardest))
Related
I know its a pretty simple question, but to anyone who is new to Javascript this can be interesting.
Is there any fastest way to parse this string and get the color for the fruit like shown below :
var fruitAndColors = "APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange"
var applecolor = getColor("APPLE") // RED
var bananaColor = getColor("BANANA") //yellow
Here is a regex match approach:
function getColor(fruitAndColors, fruit) {
return fruitAndColors.match(new RegExp("\\b" + fruit + "=([^&]+)"))[1];
}
var fruitAndColors = "APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange"
console.log(getColor(fruitAndColors, "APPLE")); // RED
console.log(getColor(fruitAndColors, "BANANA")); //yellow
For the case of searching for APPLE we use the following regex pattern:
\bAPPLE=([^&]+)
This places the key (the color) in the first capture group, which the helper function then returns.
Regex will probably be the best bet for this however it is definitely not my strong-suit. That said, here's what I came up with just some Javascript:
var fruitAndColors =
'APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange';
const getColor = (key) => {
const entries = fruitAndColors.split('&').reduce((acc, val) => {
const [fruit, color] = val.split('=');
acc[fruit] = color;
return acc;
}, {});
return entries[key];
};
var appleColor = getColor('APPLE'); // RED
var bananaColor = getColor('BANANA'); //yellow
A little class that handle that kind of url parse
class UrlParse {
#objects;
constructor(uri) {
this.uri = uri
this.objects = {}
this.parse()
}
parse() {
let arr = this.uri.split('&')
for (let a of arr) {
let arr = a.split(/\=/)
this.objects[arr[0]] = arr[1]
}
}
getName(name) {
return this.objects[name]
}
}
var fruitAndColors = "APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange"
let p = new UrlParse(fruitAndColors)
console.log(p.getName('BANANA'))
You can use a regular expression passing in the fruit, and returning the first match.
const fruitAndColors = 'APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange';
console.log(getColor('APPLE', fruitAndColors));
console.log(getColor('GUAVA', fruitAndColors));
console.log(getColor('STRAWBERRY', fruitAndColors));
console.log(getColor('BANANA', fruitAndColors));
console.log(getColor('ORANGE', fruitAndColors));
function getColor(fruit, fruitAndColors) {
const regex = new RegExp(`${fruit}=([A-Za-z]+)`);
return fruitAndColors.match(regex)[1];
}
Why don't we just use a map instead of parsing it with regex. I think that would be more efficient.
const str = "APPLE=RED&GUAVA=GREEN&STRAWBERRY=RED&BANANA=yellow&ORANGE=orange";
const fruitColorArray = str.split("&").map((value) => value.split("="));
const fruitColorMap = new Map(fruitColorArray);
function getColor(fruit) {
return fruitColorMap.get(fruit);
}
const applecolor = getColor("APPLE"); // RED
const bananaColor = getColor("BANANA"); //yellow
console.log(applecolor, bananaColor);
I'm wondering, if there is a way to filter an array or stream and apply a function A to all matches and a function B to all non-matches in JavaScript. Here is some example code that explains it a bit more:
// initial data
var names = ['Matthias', 'Maria', 'Bob', 'Anton'];
var namesWithM;
var namesWithoutM;
// gets only names starting with M, but not the others at the same time
namesWithM = names.filter(name => name.startsWith('M'))
// conditional lambda version
namesWithM = [];
namesWithoutM = [];
names.forEach(name => name.startsWith('M') ? namesWithM.push(name) : namesWithoutM.push(name));
// conditional classical version
namesWithM = [];
namesWithoutM = [];
names.forEach(function(name) {
if (name.startsWith('M'))
namesWithM.push(name)
else
namesWithoutM.push(name);
});
The very first version handles just the matches but uses filter and not forEach. Is there any way to use filter and apply a function for matches and non-matches at once? Something like this pseudo code:
names.filter(name.startsWith('M')).apply(namesWithM::push).or(namesWithoutM::push);
filter returns an array. So you can use this array to fill with name which either starts with M or not.
In the below example the filter is filling the array with name starts with M. In filter callback the name not starting with M are filled in another array
// initial data
var names = ['Matthias', 'Maria', 'Bob', 'Anton'];
var namesWithM;
var namesWithoutM = [];
namesWithM = names.filter((name) => {
if (!name.startsWith('M')) {
namesWithoutM.push(name)
}
return name.startsWith('M');
});
console.log(namesWithM, namesWithoutM);
I would use reduce to group data into 2 mentioned cases. I don't see any reason to use filter here
let names = ['Matthias', 'Maria', 'Bob', 'Anton'];
let [namesWithM, namesWithoutM] = names.reduce((acc, name) => {
if (name.startsWith('M')) {
acc[0] = [...(acc[0] || []), name]
return acc;
}
acc[1] = [...(acc[1] || []), name]
return acc;
}, [])
// simpler version
console.log(namesWithM, namesWithoutM);
let [namesWithM1, namesWithoutM1] = names.reduce((acc, name) => {
const index = Number(!name.startsWith('M'));
acc[index] = [...(acc[index] || []), name];
return acc;
}, [])
console.log(namesWithM1, namesWithoutM1);
const names = ['Matthias', 'Maria', 'Bob', 'Anton'];
function A(item){
console.log('filtered');
console.log(item);
}
function B(item){
console.log('not-ffiltered');
console.log(item);
}
const filteredNames = names.filter(name => {
const isValid = name.startsWith('M')
if(isValid)
A(name)
else
B(name)
return isValid;
})
I am trying to take an array and return a new array containing only those whose surname is 'Smith'.
I am attempting to .filter this and have been trying for quite a while but am completely out of ideas.
Please take a look at my code below, I know I am miles off, and let me kno where I might get better results? Thanks guys!
const smiths = arr.filter(function(smith) {
let nameSplit = smith.split(' ')
return nameSplit === "Smith"
});
return smiths;
Example:
arr = ['Penelope Smith', 'Charlotte Smither'] returns ['Penelope Smith']
#slouisa you almost had it, you were just missing the index for the split array.
const lastNameToFilter = "smith";
const smiths = arr.
arr = ['Penelope Smith', 'Charlotte Smither'];
const lastNameToFilter = "Smith".toLowerCase();
const smiths = arr.filter(function(fullname) {
let nameSplit = fullname.split(' ');
let lastNameIndex = 1;
return nameSplit[lastNameIndex].toLowerCase() === lastNameToFilter;
});
console.log(smiths);
filter(function(smith) {
let nameSplit = smith.split(' ');
let lastNameIndex= 1;
return nameSplit[lastNameIndex].toLowerCase() === lastNameToFilter;
});
return smiths;
You can do something like this using localeCompare to take care of case sensitivity etc:
var arr = ['Penelope Smith', 'Charlotte Smither', 'John smith']
const smiths = (a, s) => a.filter(x => x.split(' ')[1]
.localeCompare(s, 'en', {sensitivity: 'base'})==0)
console.log(smiths(arr, 'Smith'))
Another approach you could take is via endsWith and toLowerCase:
var arr = ['Penelope Smith', 'Charlotte Smither', 'John smith', 'Mark DeSmith']
const smiths = (a,s) => a.filter(x =>
x.toLowerCase().endsWith(` ${s.toLowerCase()}`))
console.log(smiths(arr, 'Smith'))
Note that endsWith does not have support in IE
I write this function but it only worked with one string ,
contains(input,words) {
let input1 = input.split(' ');
for ( var i = 0; i < input1.length; i++ ) {
if (input1[i] === words) {
return true;
}
else {
return false;
}
}
}
let contains = Str.prototype.contains('hello me want coffee','hello');
will return true
how to make it work with several words
let contains = Str.prototype.contains('hello me want coffe',['hello','want']);
You can use the some() method along with the includes() method, instead of your contains():
console.log(['hello', 'want'].some(x => 'hello me want coffe'.includes(x)));
console.log(['hello', 'want'].some(x => 'me want coffe'.includes(x)));
console.log(['hello', 'want'].some(x => 'me coffe'.includes(x)));
You can use some method in combination with split.
let contains = (str, arr) => str.split(' ').some(elem => arr.includes(elem));
console.log(contains('hello me want coffe',['hello','want']))
try indexOf() logic
function contains(input, words) {
length = words.length;
while(length--) {
if (input.indexOf(words[length])!=-1) {
return true;
}else{
return false;
}
}
}
console.log(contains('hello me want coffe',['hello','want']));
You can use RegExp to look for the strings. The pro to use RegExp is that you can be case insensitive.
// 'i' means you are case insensitive
const contains = (str, array) => array.some(x => new RegExp(x, 'i').test(str));
const arr = [
'hello',
'want',
];
console.log(contains('hello me want coffe', arr));
console.log(contains('HELLO monsieur!', arr));
console.log(contains('je veux des croissants', arr));
I am running into an issue, I have a similar array of Strings in JS:
var myArray = ["bedroomone", "bedroomonetwo", "bathroom"];
And I would like to retrieve all the elements in the array that contains the keyword 'bedroom'. How can I achieve such result ?
I tried in different ways without getting the desired result. How should I proceed ?
String.prototype.indexOf:
var PATTERN = 'bedroom',
filtered = myArray.filter(function (str) { return str.indexOf(PATTERN) === -1; });
Regexp:
var PATTERN = /bedroom/,
filtered = myArray.filter(function (str) { return PATTERN.test(str); });
String.prototype.includes (only in moderm browsers):
var PATTERN = 'bedroom',
filtered = myArray.filter(function (str) { return str.includes(PATTERN); });
var bedrooms = myArray.filter(name => name.includes('bedroom'))
Using JavaScript arrow function is much simpler
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
// search using keyword from array
var keywordToSearch = 'Arslan'; // word to search
var keyword = keywordToSearch.toLowerCase();
var names = [{id: 1, name: 'Aqib'}, {id: 2, name: 'Arslan'}];
//search keyword from names array by name
var searchResult = names.filter(word => word.name.toLowerCase().indexOf(keyword) > -1);
console.log(searchResult);
// expected output: > Array [Object { id: 2, name: "Arslan" }]
Using javascript arrow function
Improved Microfed's answer to this
var textToSearch = 'bedroom';
var filteredArray = myArray.filter((str)=>{
return str.toLowerCase().indexOf(textToSearch.toLowerCase()) >= 0;
});
You could also use the search() method
Finds the first substring match in a regular expression search.
(method) String.search(regexp: string | RegExp): number (+1 overload)
const filterList = (data, query) => {
return data.filter(name => name.toLowerCase().search(query.toLowerCase()) !== -1);
};
const House = ["bedroomone", "bedroomtwo", "bathroom"]
const filterItems = (arr, query) => {
return arr.filter(element =>
element.toLowerCase().indexOf(query.toLowerCase()) !== -1)
}
console.log(filterItems(House, "bedroom"));