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
 
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
 
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
 
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
 
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
 
maskedman99 profile image
Rohit Prasad

Python

var = input("Enter the String: ")

def capitalizeFirstLast(x):
        x = x.lower()
        x = list(x)
        x[0] = x[0].upper()
        x[len(x)-1] = x[len(x)-1].upper()

        for i in range(len(x)):
                if x[i] == ' ':
                        x[i-1] = x[i-1].upper()
                        x[i+1] = x[i+1].upper()

        return(''.join(x))

print(capitalizeFirstLast(var))
Collapse
 
baspieren profile image
Bas Pieren

Something like this with JS

function capitalizeFirstLast(string) {
  var toLowerCase = string.toLowerCase();
  var splitString = toLowerCase.split(" ");

  var transformedStrings = [];

  splitString.forEach(word => {
    var upperCaseFirstLetter = word.charAt(0).toUpperCase();
    var upperCaseLastLetter = word.charAt(word.length - 1).toUpperCase();
    var getRestOfString = word.slice(1, word.length - 1);

    var mergeString = upperCaseFirstLetter + getRestOfString + upperCaseLastLetter;

    transformedStrings.push(mergeString);
  })

  var joinStrings = transformedStrings.join(" ");

  return joinStrings;
};
Collapse
 
sabbin profile image
Sabin Pandelovitch

One letter words don't pass. Try and still i rise you will get AnD StilL II RisE

Collapse
 
pdandy profile image
Andy Thompson

Came up with this Elm solution while I was procrastinating at work today:

capitalizeFirstLast : String -> String
capitalizeFirstLast input =
  let
    capitalizeFirst = String.left 1 >> String.toUpper
    capitalizeLast  = String.right 1 >> String.toUpper
    lowercaseMiddle = String.slice 1 -1 >> String.toLower
    transform word  =
      if String.length word < 2 then
        String.toUpper word
      else
        capitalizeFirst word ++ lowercaseMiddle word ++ capitalizeLast word
  in
  String.words input
    |> List.map transform
    |> String.join " "

Not overly different from the other solutions here, but neat nonetheless.