How to add commas in between words in string in Javascript - javascript

I'm trying to add commas in between the first and last names in parentheses.
//Input:
s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
//Expected output: "(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"
What my code is currently outputting:
(CORWILL ALFRED) (CORWILL FRED) (CORWILL RAPHAEL) (CORWILL WILFRED) (TORNBULL BARNEY) (TORNBULL BETTY) (TORNBULL BJON)
I've tried a number of approaches like changing how the characters are replaced in the beginning when I reassign s (the string) so that I am not removing the commas in the first place, to then have to replace them...but when I did that, the regex I have was no longer working, and I am not sure why that is. So I tried to find another regex to use so I could work around that problem, but that has equally been a pain, so I decided to just stick to solving it this way: trying to find a way to find commas in between the first, and last names in the parentheses.
Full problem & code:
/*Could you make a program that
• makes this string uppercase
• gives it sorted in alphabetical order by last name.
When the last names are the same, sort them by first name. Last name and first name of a guest come in the result between parentheses separated by a comma.
*/
function meeting(s) {
s = s.replace(/:/g, ", ").toUpperCase();
//order alphabetically based on Last, then first name
const semicolon = ';'
let testArr = s.split(semicolon)
testArr.sort(function compare(a, b) {
var splitA = a.split(",");
var splitB = b.split(",");
var firstA = splitA[0]
var firstB = splitB[0]
var lastA = splitA[splitA.length - 1];
var lastB = splitB[splitB.length - 1];
if (lastA < lastB) return -1;
if (lastA > lastB) return 1;
if (firstA < firstB) return -1; //sort first names alphabetically
if (firstA > firstB) return 1;
return 0; //if they are equal
})
//print last names before first names with regex
let newArr = [];
for (let i = 0; i < testArr.length; i++) {
let variable = (testArr[i].replace(/([\w ]+), ([\w ]+)/g, "$2 $1"))
let comma = ","
newArr.push(`(${variable})`)
}
let finalStr;
finalStr = newArr.toString().replace(/[ ,.]/g, " ").toUpperCase();
// finalStr = finalStr.replace(/" "/g, ", ")
return finalStr
}
s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
console.log(meeting(s))
// expected result: "(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"
Any help would be appreciated, I've spent about 5 hours on this problem.The regex I am using is to switch the last name's position with the first name's position (Fred Corwill) --> (Corwill Fred). If there is a regex for me to this other than the one I am using that you could suggest, maybe I could work around the problem this way too, so far everything I have tried has not worked other the one I am using here.

That looks much more complicated than it needs to be. After splitting by ;s, map each individual element to its words in reverse order, then join:
const s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
const output = s
.toUpperCase()
.split(';')
.sort((a, b) => {
const [aFirst, aLast] = a.split(':');
const [bFirst, bLast] = b.split(':');
return aLast.localeCompare(bLast) || aFirst.localeCompare(bFirst);
})
.map((name) => {
const [first, last] = name.split(':');
return `(${last}, ${first})`;
})
.join('');
console.log(output);

That's what you need:
const str = 'Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill';
function formatString(string) {
const modifiedString = string.toUpperCase().replace(/(\w+):(\w+)/g, '($2, $1)');
const sortedString = modifiedString.split(';').sort().join('');
return sortedString;
}
console.log(formatString(str))

Using splits with maps and sorts
var s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
var res = s.split(/;/) // split into people
.map(x => x.split(/:/).reverse()) // split names, put last first
.sort((a, b) => a[0] === b[0] ? a[1].localeCompare(b[1]) : a[0].localeCompare(b[0])) // sort by last name, first name
.map(x => `(${x.join(', ')})`) // create the new format
.join(' ') // join the array back into a string
console.log(res);

Related

Capital letters in a string using the 'map' method

I want to change to make the first letters of the words in the string uppercase, and after translating into an array, I use the map method. The problem is that inheritance does not work in this method, as I understand it, because when you return the map element, the original string is returned:
const str = 'dkdg gkdj wijoerbj'
let r = str.split(' ').map((item, index) => {
item[0] = item[0].toUpperCase()
return item
})
unchanged first letters will also be returned with such a code entry(is in the map()):
item[0] = item[0].toUpperCase()
return item[0]
however, when I return the first line, the letters still become uppercase, but I do not know how to return the rest of the word in this case(is in the map()):
return item[0] = item[0].toUpperCase()
why inheritance does not work as it should, tell me, please, and how to add the rest of the word if there are no other options?
You need to cancat the first letter with rest of the string. Also these two lines item[0] = item[0].toUpperCase();return item though will convert the first letter to uppercase but it will still return the original sting because item represent the original word nut not the modified text
const str = 'dkdg gkdj wijoerbj'
let r = str.split(' ').map((item, index) => {
return item.charAt(0).toUpperCase() + item.substring(1, item.length)
});
console.log(r)
We can do this with two array map methods as bellow.
const str = 'dkdg gkdj wijoerbj';
let r = str.split(' ').map((item, index) => {
return ([...item].map((letter, i) => {
return (i == 0) ? letter.toUpperCase() : letter;
})).join('');
});
console.log(r);
const str = 'dkdg gkdj wijoerbj'
let r = str.split(' ').map(x=> x[0].toLocaleUpperCase());
console.log(r)
u can try this code to get first letters of the words in the string uppercase into new arry using map and returns capital letter of each first letter

Javascript - Replace a character inside a substring of a string

I have a string like "this/ is an example abc/def/fgh/uio to give you an example"
I'd like to target the longest word and replace on this substring any "/" by a "+".
I manage to identify the longest word and I would know how to replace ALL "/" by a "+" BUT I don't know how to replace the "/" only in the longest word.
Here's what I've got so far
//identify longest word in string
function longestWord(str) {
var words = str.split(' ');
return words.reduce(longer);
}
function longer(champ, contender) {
return (contender.length > champ.length) ? contender: champ;
}
//purely given an exemple, some strigns won't be exactly like this
var text2 = "this/ is an example abc/def/fgh/uio to give you an example"
if (longestWord(text2) > 30 ) {
text2.replace(/\//g, ' / ');
}
The problem is this will also replace the "/" on the substring "this/", and I don't want that.
How to achieve this?
Your longestWord function returns the longest word in the string, so you can pass that string alone (not a regular expression) as the first argument to .replace, and replace with (the second argument) the /\//g called on that longest word:
function getLongestWord(str) {
var words = str.split(' ');
return words.reduce(longer);
}
function longer(champ, contender) {
return (contender.length > champ.length) ? contender: champ;
}
var text2 = "this/ is an example abc/def/fgh/uio to give you an example"
const longestWord = getLongestWord(text2);
const output = text2.replace(longestWord, longestWord.replace(/\//g, '+'));
console.log(output);
#CertainPermance's solution is far more elegant (and I think performant) than this, but as I'd written the answer I thought I may as well put it in.
It's fairly similar, in truth, though in this instance we get the index of the word and use that to perform the replace, which at the time of writing I thought was necessary. Now looking at the better solution, I realise such a check is not needed, as the longest word in a string will not feature in any other words, so it's easy and safe to simply perform a replace on it.
const data = "this/ is an example abc/def/fgh/uio to give you an example";
const getLongestWordIndex = stringIn => stringIn
.split(' ')
.reduce(
(prev, curr, i) => curr.length > prev.length ? {
index: i,
length: curr.length
} : prev,
{
length: -1,
index: -1
}
).index
const replaceLongestWord = (sentence, replacer) => {
const longestWordIndex = getLongestWordIndex(sentence);
const words = data.split(' ');
return Object.values({
...words,
[longestWordIndex]: replacer(words[longestWordIndex])
}).join(' ')
}
const wordReplaceFunction = word => word.replace(/\//g, '+')
const result = replaceLongestWord(data, wordReplaceFunction);
console.dir(result)

JavaScript: sorting string according to numbers it contains

I am trying to sort a string which contains a single number from 1-9. For e.g. string is "Ho2w are1 y3ou" then resulting string should be "are1 Ho2w y3ou". For that, I have used for...of loop to iterate over a string and used split to convert it into an array of string and then used sort method but I am not getting an output. Can anyone suggest what's wrong in my program?
code ::
function order(words){
let result = "";
for (let value of words) {
result += value;
}
let splited = result.split(" ");
if(words === ""){
return "";
}
return splited.sort((a,b) => a - b);
}
order("Ho2w are1 y3ou");
You need to somehow find the number in the word that you want to use to sort. One way to do this is with String.match() and a regular expression:
let str = "Ho2w are1 y3ou"
let sorted =
str.split(' ')
.sort((a,b) => a.match(/\d+/)[0] - b.match(/\d+/)[0]) // sort based on first number found
.join(' ')
console.log(sorted)
You can use the regexp /\s+/ for splitting the array, that way you can match the tab too. And the regexp [^\d+]/g to remove those chars which are not a number and make the comparison with numbers only.
let str = "Ho2w are1 y3ou"
let sorted = str.split(/\s+/)
.sort((a, b) => a.replace(/[^\d+]/g, '') - b.replace(/[^\d+]/g, '')).join(' ');
console.log(sorted);
You can also extract characters using filter and isNaN and then use parseInt to get their integer value to use for your sorting function.
const str = "are1 Ho2w y3ou";
const ordered = str.split(" ").sort((a, b) => {
let numA = parseInt([...a].filter(c => !isNaN(c)).join(''));
numB = parseInt([...b].filter(c => !isNaN(c)).join(''));
return numA - numB;
}).join(' ');
console.log(ordered);

Split and replace text by two rules (regex)

I trying to split text by two rules:
Split by whitespace
Split words greater than 5 symbols into two separate words like (aaaaawww into aaaaa- and www)
I create regex that can detect this rules (https://regex101.com/r/fyskB3/2) but can't understand how to make both rules work in (text.split(/REGEX/)
Currently regex - (([\s]+)|(\w{5})(?=\w))
For example initial text is hello i am markopollo and result should look like ['hello', 'i', 'am', 'marko-', 'pollo']
It would probably be easier to use .match: match up to 5 characters that aren't whitespace:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer';
console.log(
str.match(/[^ ]{1,5}/g)
)
My approach would be to process the string before splitting (I'm a big fan of RegEx):
1- Search and replace all the 5 consecutive non-last characters with \1-.
The pattern (\w{5}\B) will do the trick, \w{5} will match 5 exact characters and \B will match only if the last character is not the ending character of the word.
2- Split the string by spaces.
var text = "hello123467891234 i am markopollo";
var regex = /(\w{5}\B)/g;
var processedText = text.replace(regex, "$1- ");
var result = processedText.split(" ");
console.log(result)
Hope it helps!
Something like this should work:
const str = "hello i am markopollo";
const words = str.split(/\s+/);
const CHUNK_SIZE=5;
const out = [];
for(const word of words) {
if(word.length > CHUNK_SIZE) {
let chunks = chunkSubstr(word,CHUNK_SIZE);
let last = chunks.pop();
out.push(...chunks.map(c => c + '-'),last);
} else {
out.push(word);
}
}
console.log(out);
// credit: https://stackoverflow.com/a/29202760/65387
function chunkSubstr(str, size) {
const numChunks = Math.ceil(str.length / size)
const chunks = new Array(numChunks)
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
chunks[i] = str.substr(o, size)
}
return chunks
}
i.e., first split the string into words on spaces, and then find words longer than 5 chars and 'chunk' them. I popped off the last chunk to avoid adding a - to it, but there might be a more efficient way if you patch chunkSubstr instead.
regex.split doesn't work so well because it will basically remove those items from the output. In your case, it appears you want to strip the whitespace but keep the words, so splitting on both won't work.
Uses the regex expression of #CertainPerformance = [^\s]{1,5}, then apply regex.exec, finally loop all matches to reach the goal.
Like below demo:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer'
let regex1 = RegExp('[^ ]{1,5}', 'g')
function customSplit(targetString, regexExpress) {
let result = []
let matchItem = null
while ((matchItem = regexExpress.exec(targetString)) !== null) {
result.push(
matchItem[0] + (
matchItem[0].length === 5 && targetString[regexExpress.lastIndex] && targetString[regexExpress.lastIndex] !== ' '
? '-' : '')
)
}
return result
}
console.log(customSplit(str, regex1))
console.log(customSplit('hello i am markopollo', regex1))

jQuery create new Array with doubling old one

i have problem where i need to make array from input but each input char need to be doubled in array. for example if input is ABC array need to result in AABBCC.
so i end up with this code
if (hex.length < 6) {
hex.splice(hex.indexOf(hex[i]) + 1, 0, hex[i]);
}
if input is ABC it will output AABBCC
if input is AAB it will output AAAABB
but if first and last character is same like ABA it will end up AAABBA. Why is that?
This is because indexOf() returns the first occurrence of the specified value. You can use the reduce() method instead:
const double = arr => arr.reduce((acc, next) => [...acc, next, next], []);
console.log(double(Array.from('ABA')).join(''));
Instead of explicitly iterating using indexOf which only returns the first index, you might want to try array.Map.
var a = "abc";
var b = "aba";
var c = "foo 𝌆 bar mañana mañana"
function duplicate(phrase) {
return Array.from(phrase).map(function(elem) {
return elem + elem;
}).join("");
}
var aAns = duplicate(a);
var bAns = duplicate(b);
var cAns = duplicate(c);
console.log(aAns);
console.log(bAns);
console.log(cAns);
Edit
Thanks to Michał Perłakowski for the Unicode callout!
This is a perfect opportunity to use .map():
var hex = 'ABC';
var doubledHex = Array.from(hex).map(function(i) {
return i + i;
}).join('');
console.log(hex);
console.log(doubledHex);

Categories

Resources