I am trying to capitalise the first character of each word and join all words into one string. I have managed to capitalise the first character of each word but cant seem to get .join() to work on the final result
function generateHashtag (str) {
let split = str.split(' ')
for(let i = 0; i < split.length; i++){
let finalResult = split[i].charAt(0).toUpperCase() + split[i].substring(1)
console.log(finalResult.join(''))
}
}
console.log(generateHashtag('Hello my name is')) should return ('HelloMyNameIs')
Achieving this by split is possible. first create an array of divided strings (by the delimiter ' ') and then loop around the array and capitalize the first char using the method toUpperCase and concat the rest of the string without the first letter using slice
function generateHashtag(str) {
let split = str.split(' ');
for (let i = 0; i < split.length; i++) {
split[i] = split[i].charAt(0).toUpperCase() + split[i].slice(1);
}
return split.join('');
}
console.log(generateHashtag('Hello my name is'));
More about split - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
you can do split[i] = split[i].charAt(0).toUpperCase() + split[i].substring(1) in the loop then outside loop do split.join('')
Basically you are replacing each word (split[i]) with capitalised word. Then in the end join the words.
finalResult is a String, not an Array so there is no join function.
Use this instead :
function generateHashtag (str) {
let arrayWords = str.split(' ')
const titleCasedArray = arrayWords.map(word => titleCaseWord(word))
return titleCasedArray.join('');
}
function titleCaseWord (word){
return word.slice(0,1).toUpperCase() + word.slice(1,-1).toLowerCase()
}
You can do something like this:
function generateHashtag (str) {
//returns array of strings
let split = str.split(' ')
//returns array of strings with each word capitalized
const capitalizedWordsArr = split.map( word => word.charAt(0).toUpperCase() + word.substring(1))
//returns a string by joining above array with no spaces
return capitalizedWordsArr.join('')
}
This is a perfect use-case for Array.prototype.reduce:
function generateHashtag(str) {
return str
.split(' ')
.reduce((acc, [firstLetter, ...rest]) => acc += `${firstLetter.toUpperCase()}${rest.join('')}`,
''
);
}
console.log(generateHashtag('Hello my name is')); // should return ('HelloMyNameIs')
Javascript strings are immutable so you cannot overwrite them on the go, but you can overwrite array elements.
By using String.prototype.substr() you can extract a part of the string, you can use these parts, modify it and create a new string then replace the old array element. finally returning the joined string like you wanted to
function generateHashtag(str) {
const split = str.split(' ') // array of words
for (let i = 0; i < split.length; i++)
split[i] = split[i].substr(0, 1).toUpperCase() + split[i].substr(1); // overwriting existing elements with Titlecased words
return split.join(''); // returning final string
}
console.log(generateHashtag('Hello my name is'))
You don't need to use join at all, just declare and initialize finalResult outside the loop and concatenate each word inside the loop:
function generateHashtag(str) {
const split = str.split(' '); // Array<String>
let finalResult = ''; // String
for(let i = 0; i < split.length; i++) {
const titleCased = split[i].charAt(0).toUpperCase() + split[i].substring(1);
finalResult += titleCased;
}
return finalResult;
}
console.log(generateHashtag('Hello my name is'));
However, you can simplify this code considerably by using a functional-programming (FP) style with map and reduce. See below.
I've also changed your code to use toLocaleUpperCase instead of toUpperCase and uses [0] for brevity.
It's still safe to use substring(1) for single-character strings, it just returns ''.
function generateHashtag(str) {
return ( str
.split(' ')
.map( word => word[0].toLocaleUpperCase() + word.substring(1).toLocaleLowerCase() )
.reduce( ( word, concat ) => concat + word, "" )
);
}
I forgot that join() can still be used instead of reduce (and will have an optimized implementation inside the JS engine anyway):
I've also moved the map function's logic to a named function toTitleCase.
function generateHashtag(str) {
const toTitleCase( word ) => word[0].toLocaleUpperCase() + word.substring(1).toLocaleLowerCase();
return ( str
.split(' ')
.map( word => toTitleCase( word ) ) // or just `.map( toTitleCase )`
.join()
);
}
The return statement has parens to prevent unwanted automatic-semicolon-insertion which would otherwise break the function.
If you want something similar to your code, but working, i would do this:
function generateHashtag (str) {
let split = str.split(' ')
let newStr = []
for (let i = 0; i < split.length; i++){
newStr.push(split[i].charAt(0).toUpperCase() + split[i].substring(1))
}
return newStr.join('')
}
You could also choose to do this task using a 'regular expression'.
https://cheatography.com/davechild/cheat-sheets/regular-expressions/
Here is a quick implementation:
const generateHashtag = str => {
// regular expression to capitalize the words
const regEx = /(\b[a-z](?!\s))/g
str = str.replace(regEx, (char) => {
return char.toUpperCase()
});
// remove spaces, return
return str.split(' ').join('')
}
Same code, but with less readability:
const generateHashtag = str => {
return str.replace(/(\b[a-z](?!\s))/g, (char) => {
return char.toUpperCase()
}).split(' ').join('');
}
function generateHashtag (str) {
return str.replace(/\b\S/g, e => e.toUpperCase()).replace(/\s/g,'');
}
console.log(generateHashtag('Hello my name is'))
\b: bondary \S: non space \s: space.
https://regex101.com/
//try this code solve your problem
const generateHashtag = str => {
let split = str.split(' ')
let finalResult = []
for (word of split) {
finalResult.push(word[0].toUpperCase() + word.substring(1))
}
return finalResult.join('')
}
console.log(generateHashtag('Hello my name is'))
Related
i have a string i need to convert it into a array of object
const str = "addias (brand|type) sneakers(product) for men(o)"
expected output
let output = [
{
key:"addias",
value:["brand","type"]
},
{
key:"sneakers",
value:["product"]
},
{
key:"for men",
value:[]
}
]
code i tried
function gerateSchema(val) {
let split = val.split(" ")
let maps = split.map((i) => {
let obj = i.split("(")
let key = obj[0].replaceAll(/\s/g, "")
let cleanValue = obj[1].replace(/[{()}]/g, "")
let stripedValues = cleanValue.split("|")
return {
key: key,
value: stripedValues,
}
})
return maps
}
let out = gerateSchema(str)
but this breaking when there is some word with space for example for men
how to do split with a regex
One approach would be first do a regex find all to find all key/value combinations in the original string. Then, iterate that result and build out a hashmap using the word keys and the array values.
var str = "addias (brand|type) sneakers(product) for men(o)";
var matches = str.match(/\w+(?: \w+)*\s*\(.*?\)/g, str);
var array = [];
for (var i=0; i < matches.length; ++i) {
var parts = matches[i].split(/\s*(?=\()/);
var map = {};
map["key"] = parts[0];
map["value"] = parts[1].replace(/^\(|\)$/g, "").split(/\|/);
array.push(map);
}
console.log(array);
The first regex matches each key/value string:
\w+ match a word
(?: \w+)* followed by a space, and another word, the quantity zero or more times
\s* optional whitespace
\( (
.*? pipe separated value string
\) )
Then, we split each term on \s*(?=\(), which is the space(s) immediately preceding the (...|...) term. Finally, we split the value string on pipe | to generate the set of values.
An alternative way could be this.
const str = "addias (brand|type) sneakers(product) for men(o)"
const array = str.split(')').filter(i => i.length).map(i => {
const item = i.split('(');
return {
key: item[0].trim(),
value: item[1].split('|')
}
})
console.log(array)
It may be simpler to use the exec method to iterate over the patterns the regex finds.
const str = 'addias(brand|type|size|color) sneakers(pro) for men(o)';
// The regex looks for an initial group of letters,
// then matches the string inside the parentheses
const regex = /([a-z]+)\(([a-z\|]+)\)/g;
let myArray;
const arr = [];
while ((myArray = regex.exec(str)) !== null) {
// Destructure out the key and the delimited string
const [_, key, ...rest] = myArray;
// `split` on the string found in `rest` first element
const values = rest[0].split('|');
// Finally push a new object into the output array
// (removing "o" for whatever reason)
arr.push({
key,
value: values.filter(v => v !== 'o')
});
}
console.log(arr);
With a little help from regex101.com, derived the following regex expressions and the following code.
([^\(]+)\(([^\)]*)\) which breaks down into
([^\(]+) - capture 1 or more chars up to the first ( as group 1
\( - swallow the left parens
([^\)]*) - capture everything up to the next occurrence of ) as group 2
\) - swallow the right parens
and I was starting to [^|]+ - to parse the text of group 2, but it's actually simpler with a simple split statement.
function generateSchema(str) {
const regex = /([^\(]+)\(([^\)]*)\)/mg; // captures the 'word (word)' pattern
let m;
let output = [];
let obj = {};
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
m.forEach((match, groupIndex) => {
if (groupIndex === 1) {
obj = {};
obj.key = match.trim();
} else if (groupIndex === 2) {
obj.value = match.split('|').map(i=>i.trim());
output.push(obj);
}
});
}
return output;
}
const str = "addidas (brand | type ) sneakers(product) for men(o)";
console.log(generateSchema(str));
Need help inside the for loop to flip each character with the character before it.
function flip(str) {
//split string
//iterate through split string
//return joined string
var splitt = str.split('');
for(var i = 0; i < splitt.length; i++){
//flip every character with one before it
}
}
var output = flip('otatl');
console.log(output); // -> 'total'
function split(str) {
let splitt = str.split('');
for (let i=0; i<splitt.length-1; i+=2) {
const temp = splitt[i];
splitt[i] = splitt[i+1];
splitt[i+1] = temp;
}
return splitt.join('');
}
You can use ES6 destructuring assignment.
function flip(str) {
//split string
//iterate through split string
//return joined string
let splitt = str.split('');
for (let i=0; i < splitt.length; i++){
//flip every character with one before it
if (i%2 == 1) {
[splitt[i-1], splitt[i]] = [splitt[i], splitt[i-1]];
}
}
return splitt.join('');
}
let output = flip('otatl');
console.log(output); // -> 'total'
You can combine this technique with gillyb's loop pattern to reduce the iterations as follows:
function flip(str) {
//split string
//iterate through split string
//return joined string
let splitt = str.split('');
for (let i=1; i < splitt.length; i+=2){
//flip every character with one before it
[splitt[i-1], splitt[i]] = [splitt[i], splitt[i-1]];
}
return splitt.join('');
}
let output = flip('otatl');
console.log(output); // -> 'total'
Can do something similar with regex and array manipulation
const flip = (stringToFlip) => stringToFlip
.split(/(.{2})/) // array of strings of 2 chars
.map((e) => e.split('') // convert each string piece to array
.reverse() // reverse array
.join('') // convert array piece back to string
)
.join(''); // combine all parts
const result = flip('otatl');
console.log("flip('otatl')");
console.log(result);
If we're not restricted to for loops, this is my (slightly too code golf-ish?) answer:
const flip = (str) =>
str
.split('')
.reduce((a, v, i) => (a[i + ((i % 2) * -2 + 1)] = v, a), [])
.join('');
console.log(flip('otatl'));
console.log(flip('lfpi'));
I'm sorry I am late to the party but you can use reduce().
let input = "vanjskojfdghpja";
let output = input
.split('')
.reduce(([o,p],c,i) => i%2?[o+c+p,'']:[o,c],['',''])
.join('');
console.log(output);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Add a removeLetter function that takes a string and a letter. The result of the function should be string, which does not have the specified character in letter.
How to do peple?
function deleteLetter(string, letter) {
let final = '';
for (let i = 0; i<string.length; i++) {
if (string[i] === letter) {
final.concat(string[i])
}
return final;
}
}
You should return the result at the end of the function, not in the for loop
function deleteLetter(string, letter) {
let final = ""
for (let i = 0; i < string.length; i++) {
if (string[i] !== letter) {
final += string[i]
}
}
return final
}
console.log(deleteLetter("asdasd", "a"))
With ES2021 you'll be able to use String.replaceAll (already available on firefox stable (79) and chrome beta(85)/canary(86))
console.log("test".replaceAll("t", ""))
You can just use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
let str = 'test'
let replaced = str.replace('e', '')
console.log(replaced) // tst
But remember that only first occurrence will be replaced when u use string as first parameter. Use regex solution when you want to remove all of the letters
const removeLetter = (str, letter) =>
str.split('').filter(n => !n.includes(letter)).join('');
console.log(removeLetter('asd', 'a'));
or
const removeLetter = (str, letter) => str.replace(/[^letter]/, '');
console.log(removeLetter('asd', 'a'));
using splice & indexOf
function delLetter(word,letter){
let wordArr = word.split('');
let idx = wordArr.indexOf(letter);
wordArr.splice(idx,1); // deleted here
return wordArr.join('');
}
console.log(delLetter('twinkle','w'))
I'm trying to write a code that finds all words that have 4 (in this case) characters. So my expected output would be this that abcd
My current code looks like this, the problem with it, it's only finding the first word this and it stops looking for further that abcd it.
let string = 'aa this bb cc that abcd';
function longWord(str) {
let words = str.split(' ');
let longWord = '';
for (let word of words) {
if (word.length > longWord.length) longWord = word;
}
return longWord;
}
console.log(longWord(string));
From my understanding i need to include a loop.
Change from for (let word of words) {
To this for (var i = 1; i < words.length; i++) {
But then after this i'm lost :(
Looking at google i'm able to find only code with similar to mine or outputting a char number.
You can use split with filter like so.
split will create an array of strings seperated by space. filter will return only strings with length of 4 characters. Finally, join will return the array as space seperated strings.
let string = 'aa this bb cc that abcd';
function longWord(str) {
return str.split(' ').filter(x => x.length === 4).join(' ');
}
console.log(longWord(string));
string.split(' ').filter(x => x.length === 4).map(x => x)
This piece of code should give you the expected output
There you go
split: create an array with all the words
filter: get only the words with 4 chars
join: create a string with all elements splitted with a space
var el = string.split(' ').filter(x => x.length == 4).join(' ');
If I understand correctly there are two tasks:
1. find the largest character count for a word in the string, and
2. find all the words that match this count
const longestWords = str => {
const words = str.split(/\s+/g);
const maxCount = Math.max.apply( null, words.map( word => word.length ));
return words.filter( word => word.length === maxCount );
};
https://jsfiddle.net/pkxwfmb2/
console.log( longestWords("aa this bb cc that abcd") );
// [ "this", "that", "abcd" ]
console.log( longestWords("aa this bb cc that abcdef") );
// [ "abcdef" ]
console.log( longestWords("a bb c dd e f gg") );
// [ "bb", "dd", "gg" ]
Try this:
let string = 'aa this bb cc that abcd';
function longWord(str) {
let words = str.split(' ');
let output = [];
for (let i = 0; i < words.length; i++) {
if (words[i].length == 4)
output.push(words[i]);
}
return output.join(',');
}
console.log(longWord(string));
You'll get your expected output.
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));