loading...

Daily Challenge #38 - Middle Name

thepracticaldev profile image dev.to staff ・1 min read

Your challenge today is to initialize an individual's middle name (if there is any).

Example:
'Jack Ryan' => 'Jack Ryan'
'Lois Mary Lane' => 'Lois M. Lane'
'Dimitri' => 'Dimitri'
'Alice Betty Catherine Davis' => 'Alice B. C. Davis'

Good luck!


This challenge comes from manonacodingmission on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge for a future post? Email yo+challenge@dev.to with your suggestions!

Discussion

pic
Editor guide
 

CSS

/* the first letter of each word will have a regular size */
.mn span::first-letter {
  font-size: 1rem;
} 

/* the words in the middle (not first or last) will have a font-size of 0 */
.mn span:not(:first-child):not(:last-child) {
  font-size: 0;
  display: inline-block;
}

/* add a . at the end of each shortened word */
.mn span:not(:first-child):not(:last-child)::after {
  content: ".";
  font-size: 1rem;
}

Wrap each word in a span, and add the class "mn" to the container.
Live demo on CodePen.

 

I also did a JavaScript version on that same demo:

const middleName = name => name.split(' ')
                               .map((val, idx, arr) => idx == 0 || idx == arr.length - 1 
                                                        ? val 
                                                        : val[0] + ".")
                               .join(' ');
 

If you select-and-copy the names, the full name is copied instead of the shortened one.

 

Not the best solution: ))

function findMiddleName(str) {
    const words = str.split(' ');
  let result = '';
  if(words.length <= 2)
    return result = str
   else{
   let middleNames = ''
   for(let i = 1; i < (words.length - 1); i++)
    middleNames += (words[i].slice(0,1) + '. ') 
    return result = `${str.split(' ')[0]} ${middleNames}${str.split(' ')[words.length - 1]}`
   }
}

console.log(findMiddleName('Jack Ryan'));
console.log(findMiddleName('Lois Mary Lane'));
console.log(findMiddleName('Dimitri'));
console.log(findMiddleName('Alice Betty Catherine Davis'));
 

Ruby solution

I just changed a few things in a similar function from singl.page. Doesn’t use join(). Works when only a single name is provided.

def middle_names(fullname)
  String.new.tap { |result|
    fullname.split(' ').then { |words|
      words.map.with_index { |word, i|
        case i
        when 0
          result << word.capitalize
        when words.length - 1
          result << ' '
          result << word.capitalize
        else # middlename
          result << " #{word[0].upcase}."
        end
      }
    }
  }
end
 

PHP Solution

<?php

 $fullName = $argv[1];
 $components = explode(' ', $fullName);
 for ($i=1; $i<= count($components) - 2; $i++) {
     $components[$i] = strtoupper($components[$i][0]) . '.';
 }

 echo implode (' ', $components);
 
def initialize(full_name):
    names = full_name.split()
    return ' '.join(
        f'{name[0]}.' if index > 0 and index < len(names) - 1 else name
        for index, name in enumerate(names)
    )
 

Here's mine, with a more functional approach - also takes into account name strings that have erroneous spaces

jsbin.com/gedejih/edit?js,console

function formatName(name) {
    /* Trim out any spaces at the beginning or end,
     * split the name into segments,
     * and filter out empty strings. */
  const splitName = name
    .trim()
    .split(' ')
    .filter(n => n.length > 0)

  return splitName.map((namePart, index) => {
    /* Return the first and last names as they are */
    if (index === 0 || index === splitName.length - 1) return namePart

    /* Otherwise, get the first character,
     * make sure it is capitalized,
     * and return it with a `.` */
    return `${namePart[0].toUpperCase()}.`

  }).join(' ')
}


const formattedNames = names.map(formatName) 
 

Javascript

This was fun :)

const initialiseMiddleNames = (fullName) => {
  const names = fullName.split(' ')
  if (names.length <= 2) return fullName

  const firstName = names.shift()
  const lastName = names.pop()
  const initials = names.map(name => name.charAt(0))

  return `${firstName} ${initials.join('. ')}. ${lastName}`
}

initialiseMiddleNames('Jack Ryan') // Jack Ryan
initialiseMiddleNames('Lois Mary Lane') // Lois M. Lane
initialiseMiddleNames('Dimitri') // Dimitri
initialiseMiddleNames('Alice Betty Catherine Davis') // Alice B. C. Davis
 

Python

def initialize_names(name):
    name= name.split(' ')
    if len(name) <=2:   return ' '.join(name)
    new_name=[]
    for i in range(len(name)):
        if i != 0 and i != (len(name)-1):    new_name.append(name[i][0]+'.')
        else:   new_name.append(name[i])
    return ' '.join(new_name)
 

Here is the simple solution with Python:

def initialize_names(name):
    name_array = name.split(' ')

    if len(name_array) == 2 or len(name_array) == 1:
        return name

    result = name_array[0] + " "
    name_index = 1
    while name_index <= len(name_array)-2:
        result += name_array[name_index][0] + ". "
        name_index += 1

    result += name_array[-1]

    return result
 
const initializeMiddleNames = (name) => {
    const nameArr = name.split(' ')
    for (let index = 1; index < nameArr.length -1; index++) {
        nameArr[index] = `${nameArr[index].substring(0, 1)}.`;
    }
    return nameArr.join(' ') 
}


initializeMiddleNames('Jack Ryan') // Jack Ryan
initializeMiddleNames('Lois Mary Lane') // Lois M. Lane
initializeMiddleNames('Dimitri') // Dimitri
initializeMiddleNames('Alice Betty Catherine Davis') // Alice B. C. Davis

 
def initializeName(name: str):
    name = name.split(" ")
    if (len(name) >= 3):
        #loop from first name to last name.
        for i in range(1, len(name)-1):
            name[i] = name[i][0] + "."
    name = ' '.join(name)
    return name
 

Python.

I had two attempts at this, my first was only for full names up to three words but after realising I needed to expand the program to work on more I rewrote the program. Both and posted below and annotated.

First attempt

def initialize(full_name):
  names = full_name.split()
  num_names = len(names)
  if num_names == 3:
    Middle_initial = names[1]
    print(names[0],Middle_initial[0],".",names[2])
  elif num_names <=2:
    print(names[0],names[1])
  else:
    print("Compatability for names of 4 or more has not been added.")
full_name = input("Full Name: ")
if not full_name == "":
  initialize(full_name)

Second Attempt

def initialize(full_name):
  start = 1
  names = full_name.split()
  num_names = len(names)
  if num_names >= 3:
    answer = ""
    change = num_names-1
    while not start == change:
      a = names[start]
      a = a[0]
      start = start + 1
      answer = answer + a.upper() + "."
    print(names[0],answer,names[num_names-1])
  else: print(full_name)
full_name = input("Full Name: ")
if not full_name == "":
  initialize(full_name)

I wasn't too happy on the result,
Any pointers on how to I could improve my code would be great!

 

But ey it works,

Python 3.7.4 (default, Jul  9 2019, 00:06:43)
[GCC 6.3.0 20170516] on linux
Full Name: Ben Dark Aye Daggity do yee Dover
Ben D.A.D.D.Y. Dover

😁..I am uh, very, mature.

 

JavaScript:

function initializeNames(name){
  const names = name.split(' ');
  if (names.length > 2) {
    return names.map((v, i) => {
      if (i === 0 || i === names.length-1) {
        return v;
      }
      return v[0].toUpperCase() + '.';
    }).join(' ');
  }
  return name;
}
 

My solution in js

const initialize = (fullname) => fullname.split(' ').map((name, index, names) => (index === 0 || index === names.length - 1) ? name : `${name[0]}.`).join(' ');
 

ruby <3

def initialize_middle_name(n)
  n.split.then { |f, *mid, l| [f, *mid.map { @1.upcase[0] + ?. }, *l].join ' ' }
end
 

Python :

def middle_name(full_name):
    names = full_name.split(' ')
    return ''.join([name + ' ' if i == 0 or i == len(names)-1 else name[0]+'. ' for i, name in enumerate(names)])
 

Nice,
Here's my Python solutions!
dev.to/teotcd/comment/e6fl