DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #190 - capitalizeFirstLast

For this challenge, you will have to write a function called capitalizeFirstLast or capitalize_first_last. This function will capitalize the first and last letter of each word, and lowercase what is in between.

capitalizeFirstLast "and still i rise" -- "AnD StilL I RisE"

Rules:

  • The function will take a single parameter, which will be a string.
  • The string can contain words separated by a single space.
  • Words are made of letters from the ASCII range only.
  • The function should return a string.
  • Only the first and last letters are uppercased.
  • All the other letters should be lowercased.

Examples:

capitalizeFirstLast "and still i rise"               -- "AnD StilL I RisE"
capitalizeFirstLast "when words fail music speaks"   -- "WheN WordS FaiL MusiC SpeakS"
capitalizeFirstLast "WHAT WE THINK WE BECOME"        -- "WhaT WE ThinK WE BecomE"
capitalizeFirstLast "dIe wITh mEMORIEs nOt dREAMs"   -- "DiE WitH MemorieS NoT DreamS"
capitalizeFirstLast "hello"                          -- "HellO"

Good luck!


This challenge comes from aminnairi here on DEV. Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Top comments (24)

Collapse
 
willsmart profile image
willsmart • Edited

An easy option is to start off by lowercasing the whole thing...
(JS)

capitalizeFirstLast = s => s.toLowerCase().replace(/\b\w|\w\b/g, c => c.toUpperCase())

Regex matches single letters preceded by a word boundary or followed by a word boundary.

Running through the examples:

[
  "and still i rise",
  "when words fail music speaks",
  "WHAT WE THINK WE BECOME",
  "dIe wITh mEMORIEs nOt dREAMs",
  "hello"
].map(s => `"${s}" -> "${capitalizeFirstLast(s)}"`).join("\n")

>> 

"and still i rise" -> "AnD StilL I RisE"
"when words fail music speaks" -> "WheN WordS FaiL MusiC SpeakS"
"WHAT WE THINK WE BECOME" -> "WhaT WE ThinK WE BecomE"
"dIe wITh mEMORIEs nOt dREAMs" -> "DiE WitH MemorieS NoT DreamS"
"hello" -> "HellO"
Collapse
 
khauri profile image
Khauri

Nice! Super clean.

Collapse
 
willsmart profile image
willsmart

Thanks!

Collapse
 
khauri profile image
Khauri • Edited

Javascript + Regex "One" liner.

function capitalizeFirstLast(string) {
  return string.replace(/(\w)((\w*)(\w))?/g, (_, a, __, b, c) => [a.toUpperCase(), b && b.toLowerCase(), c && c.toUpperCase()].filter(Boolean).join(''))
}

Click here if you're curious what the regular expression does

Collapse
 
nombrekeff profile image
Keff

Cool, many ways of doing this.

This is what I came up with:

function capitalizeFirstLast(string = "") {
  const _firstLastWord = word => {
    if (!word || word.length <= 1) {
      return word.toUpperCase();
    }

    let len = word.length;
    const upperAt = i => word.charAt(i).toUpperCase();
    return `${upperAt(0)}${word.substr(1, len - 2)}${upperAt(len - 1)}`;
  };

  return string.length
    ? string
        .toLowerCase()
        .split(" ")
        .map(_firstLastWord)
        .join(" ")
    : string;
}
Collapse
 
tails128 profile image
Tails128 • Edited

The most straightforward way to fix this is probably to do something as:

export const capitalizeFirstLast = (inputString: string): string => 
    inputString
        .split(' ')
        .reduce((accumulator: string, entry: string) =>
            { 
                let fixedWord: string = capitalizeFirstLastInWord(entry);

                return `${accumulator} ${fixedWord}`;
            }, "");


const capitalizeFirstLastInWord = (word: string) =>
    word.charAt(0).toUpperCase()
    + word.slice(1, -1).toLowerCase()
    + word.charAt(entry.length -1).toUpperCase()

but probably there are better ways to do this :P

EDIT: Ofc some tuning is required if we also accept punctuation and, numbers or any other characters of sort, but the requirements state letters, so...

Collapse
 
aminnairi profile image
Amin

I think there are a couple mistakes in your solution.

In your capitalizeFirstLastInWord function, you are using the variable entry. I think you meant word?

And in your capitalizeFirstLast function, you are using an undefined variable fixedWord. Maybe this was the return value of your previous function call?

Other than that, I really like how you used the reduce method to solve this one!

Collapse
 
tails128 profile image
Tails128 • Edited

You are 100% right, I did some last-minute refactoring and I was a bit distracted! :P

I will edit it for future readers :)

About the reduce part: The idea came because last year I was able to work with an
awesome team which enforced very good practices & a very cool "implementation"
of functional programming, I miss that team a lot!

Collapse
 
vidit1999 profile image
Vidit Sarkar

C++

string capitalizeFirstLast(string s){
    string modifiedString = "";
    for(int i=0;i<s.length();i++){
        if(i==0 || (i>0 && s[i-1]==' ') || (i<s.length()-1 && s[i+1] == ' ') || i==s.length()-1){
           modifiedString += char(toupper(s[i]));
        }
        else{
            modifiedString += char(tolower(s[i]));
        }
    }
    return modifiedString;
}

Python one liner

def capitalizeFirstLast(s):
  return  " ".join([word[0].upper()+word[1:-1].lower()+(word[-1].upper() if len(word)>1 else "") for word in s.split()])
Collapse
 
interludedesign profile image
Chris Swann • Edited

First try in Ruby, I think this can be done without splitting and rejoining.

def capitalizeFirstLast(string)

    string.split(' ').each do |word|
        word.downcase!
        word.sub!(/\A./) {|match| match.upcase} # First Char
        word.sub!(/.\z/) {|match| match.upcase} # Last Char
    end.join(' ')

end

puts capitalizeFirstLast "tHIs is my string"
# => ThiS IS MY StrinG
Collapse
 
viktordimitrievski profile image
Viktor

First & Fast & Last try with JS

capitalizeFirstLast = sentence => {
    var arrWords = sentence.toLocaleLowerCase().split(" ");
    var newArrWords = [];

    arrWords.forEach((x,i)=> {
        var wordLength = x.length;
        if(wordLength > 2){
            newArrWords.push(x.charAt(0).toUpperCase() + x.substr(1,wordLength-2) + x.charAt(wordLength - 1).toUpperCase());
        }
        else{
            newArrWords.push(x.toUpperCase());
        }
    });
return newArrWords.join(" ");
}
Collapse
 
navdeepsingh profile image
Navdeep Singh • Edited
console.clear();
const capitalizeFirstLast = (str) => {
  let strArr = str.split(" ");
  let parseStr = strArr.map(item => {
        itemArr = [...item];
        midStr = itemArr.slice(1,itemArr.length-1).join('');
        return item.length > 1 ? item[0].toUpperCase() + midStr.toLowerCase() + item[item.length-1].toUpperCase() : item[0].toUpperCase();      
  }).join(' ');
  console.log(parseStr);  
}
capitalizeFirstLast('my name is NAVDEEP singh')

JSBin Link

Collapse
 
jehielmartinez profile image
Jehiel Martinez

JAVASCRIPT ANSWER

function capitalizeFirstLast(str) {
    return str.replace(/[^\s]+/g, (match) => {
        replaceStr = '';
        const len = match.length;

        for(i=0; i<len; i++){
            if(i === 0 || i === len-1){
                replaceStr = replaceStr + match[i].toUpperCase();
            } else {
                replaceStr = replaceStr + match[i].toLowerCase();
            }
        }

        return replaceStr
    });
};
Collapse
 
craigmc08 profile image
Craig McIlwrath • Edited

Haskell

import Data.Char (toUpper, toLower)

capitalizeFirstLast :: String -> String
capitalizeFirstLast = unwords . map f . words
  where f (c:[]) = [toUpper c]
        f (c:cs) = toUpper c : map toLower (init cs) ++ [toUpper (last cs)]