有没有更好的方法来返回名字和名字的首字母?

时间:2013-08-21 14:59:11

标签: ruby-on-rails ruby

名称为“Rigobert Song”如何返回“Rigobert S.”?

名称可以是Rigobert J. Song,也可以是Rigobert。我想为之前的Rigobert S.和后者的Rigobert返回。

我写了这个,有效。是否有更多“Ruby方式”?

def initials_for(user)
  if user.name.split.size > 1
    "#{user.name.split.first} #{user.name.split.last[0]}"
  else
    user.name
  end
end

5 个答案:

答案 0 :(得分:4)

"Rigobert J. Song"
.gsub(/\s+.+\s+/, " ").sub(/(?<=\s\S).+/, ".")
# => "Rigobert S."

"Rigobert Song"
.gsub(/\s+.+\s+/, " ").sub(/(?<=\s\S).+/, ".")
 # => "Rigobert S."

"Rigobert"
.gsub(/\s+.+\s+/, " ").sub(/(?<=\s\S).+/, ".")
 # => "Rigobert"

答案 1 :(得分:2)

您不必多次拆分。你可以把它变成一个变量

def initials_for(user)
  name_arry = user.name.split
  name_arry.size > 1 ? "#{name_arry.first} #{name_arry.last[0]}" : user.name
end

答案 2 :(得分:1)

这也会奏效。但我不知道它是否一定是一个“更好”的解决方案。

def initials_for(user)
  parts = user.name.split
  name = parts.first
  name += " #{parts.last[0]}." if parts.length > 1
  name
end

答案 3 :(得分:1)

由于您将其标记为ruby-on-rails,我假设您有present?可用...

def initials_for(full_name)
  (first_name, *, last_name) = full_name.split
  [first_name, name_initial(last_name)].reject(&:blank?).join(" ")
end

def name_initial(name)
  if name.present?
    "#{name[0]}."
  else
    ""
  end
end

puts initials_for(user.name)

首先,我在这个帮助器中考虑了用户的使用,这是这个函数不需要知道的依赖。按照放置行中的指示传入字符串。

我做了一个帮助来处理第二个初始化,其中有一个句号,其他几个表示..然后将这些部分收集到一个数组中,拒绝空白部分,并用空格连接它们。

请注意在分割的左侧使用splat和intent揭示变量。如果您尝试它,您应该看到first_name始终具有最左侧的名称,last_name始终具有最右侧的名称,如果只存在一个名称,则为nil。

在处理第一个,最后一个,中间名,首个和常用名的变体时,我使用这种拒绝和加入的模式,留下一个没有额外字符等的可读名称。

答案 4 :(得分:-1)

编辑以正确处理提问者的示例字符串

我喜欢使用正则表达式。这允许使用名字和/或姓氏中的任何字符。字符串中最多必须有两个空格。

如果空格为零,则所有字符都将作为名字放在捕获组1中。

如果有一个空格,则空格前的字符将作为名字放在捕获组1中,空格后的字符将作为姓氏放在捕获组3中。

如果有两个空格,则第一个空格前的字符放在捕获组1中;捕获组2中空格之间的字符;和捕获组3中第二个空格后的字符。

#output
Testing Rigobert Song
Rigobert S.
Testing Rigobert J. Song
Rigobert S.
Testing Rigobert J.Song
Rigobert J.
Testing RigobertJ.Song
RigobertJ.Song
Testing Rigobert
Rigobert


tests = [ "Rigobert Song", "Rigobert J. Song", "Rigobert J.Song", "RigobertJ.Song", "Rigobert", ]
regex=\
 /^([^ ]*) ?([^ ]* )?([^ ]+)?$/
#- - - - - - - - - - - - - - -
# ^- - - - - - - - - - - - - - Match start of string here
#  ^ - - ^ - - - - - - - - - - Begin/End capture group 1
#   ^^^^^- - - - - - - - - - - Match 0 or more of any non-space character
#         ^^ - - - - - - - - - Match zero or one literal space
#           ^- - - ^ - - - - - Begin/End capture group 2
#            ^^^^^ - - - - - - Match 0 or more non-space characters...
#                 ^- - - - - - ... with exactly one trailing space
#                   ^- - - - Make Capture group 2 optional (match 0 or 1)
#                    ^ - - ^ - Begin/end capture group 3
#                     ^^^^^- - Match 1 or more non-space characters
#                           ^- Make capture group 3 optional
#                            ^ Match end of string here

tests.each do |str|
  puts "Testing #{str}"
  match = regex.match(str)
  if(match != nil)
    first = match[1]
    middle = match[2] || ""
    last = match[3] || ""
    if(first != "" && last != "")
      puts(first+" "+last[0].chr+".") # ruby 1.8
      #puts(first+' '+last[0]+".")     # ruby 1.9
    else
      if(first != "" && last == "")
        puts(first)
      else
        puts('Invalid name format')
      end
    end
  else 
    puts('No regex match')
  end
end