단어를 뒤집고 모음을 이동하고 모든 것을 다운 케이스

Aug 19 2020

저는 Ruby를 처음 접했습니다.

이 함수는 여러 단어의 문자열을 가져 와서 단어의 순서를 반대로합니다. 또한 각 단어에 대해 모음을 가져와 단어의 끝으로 이동합니다. 또한 모든 것을 축소합니다. 따라서, Hello World!될 것입니다 wrld!o hlleo.

일부 Ruby 기능을 사용하려고하는데, 그래서 말하자면 한 줄짜리입니다. 기본적으로 스타일 제안을 찾고 있습니다. 그런 일을 이런 식으로하는 것이 적절합니까 (한 줄?). 작업을 더 빨리 수행 할 수있는 기능이 있다고 확신하므로 코드가 매우 길고 복잡하기 때문에 이러한 제안에도 열려 있습니다. 또한 추가 패키지 / 보석없이 기본 Ruby로만 작성하고 싶었습니다.

누군가가 Rubocop과 Style Guide를 제안했기 때문에 확인해 보겠습니다.

  def funky_words(s)
    s.strip.gsub(/\s+/, " ").split(" ").reverse.instance_eval{map{|elt| elt.gsub(/([aeiou])/i,"")}}.
    zip(s.strip.split(" ").reverse.map{|elt| elt.scan(/([aeiou])/i).flatten}.instance_eval{map{|elt| elt.join}}).
    map(&:join).join(" ").downcase
    #first "line" reverses word order removes vowels, second "line" captures vowels, last "line" joins vowels and all words
  end

답변

3 FMc Aug 26 2020 at 08:45

한 줄짜리는 재미 있지만 세상에 더 이상 필요하지는 않습니다. 즉, 그렇게 읽을 수 없을 필요는 없습니다. 당신이 그 기능을 유지해야한다면 당신의 미래의 두뇌는 지금부터 1 년 후에 무엇을 말할 것입니까?

다음은 (1) 줄을 아낌없이 사용하고, (2) 논리의 계층 구조를 전달하기 위해 예쁘게 인쇄 된 데이터 구조 방식으로 코드를 들여 쓰기하여 긴 "한 줄"을 읽을 수있는 확장 가능한 기술을 보여주는 접근 방식입니다 (코드는 데이터입니다. 결국), 그리고 (3) 독자에게 논리와 의도를 지원하는 주석을 포함합니다.

def funky_words(s)
  (
    # Split into words.
    s
    .split
    .reverse_each
    .map { |word|
      # Within each word, push vowels to the end, while preserving
      # original order within consonants and vowels.
      word
      .each_char
      .sort_by.with_index { |c, i| "aeiouAEIOU".include?(c) ? [1, i] : [0, i] }
      .join
    }
    # Rejoin the new words.
    .join(" ")
  )
end
1 CarySwoveland Jan 19 2021 at 11:17

솔루션은 다음을 수행합니다.

  • 문자열을 다운 케이스
  • 결과 문자열을 단어 배열로 변환
  • 단어 배열 반전
  • 모음이 끝에 있고 모음과 비 모음 모두에 대해 순서가 유지되도록 배열의 각 단어를 변환합니다.
  • 결과 배열의 단어를 결합하여 문자열을 형성합니다.

두 번째 작업부터 시작하겠습니다. 코드를 더 읽기 쉽게 만들고 테스트 속도를 높이기 위해 별도의 메서드를 만들어 보겠습니다.

VOWELS = 'aeiou'
def shove_vowels_to_end(word)
  vowels = ''
  non_vowels = ''
  word.each_char do |char|
     if VOWELS.include?(char)
       vowels << char
     else
       non_vowels << char
     end
  end
  [non_vowels, vowels].join
end

String # each_char , String # include?를 참조하십시오 . 및 String # join .

곁에 : word.chars do |char|...대신 쓸 수 word.each_char do |char|...있었지만 전자는 word.chars중간 배열 을 반환하는 단점이 있는 반면 후자는 열거자를 반환하여 메모리를 덜 소비합니다.

해 보자:

shove_vowels_to_end("atlastdisgonehurray!")
  #=> "tlstdsgnhrry!aaioeua"      

원하는 경우 VOWELS집합을 만들 수 있습니다 ( Set # include? 를 사용 하여 계산 속도를 높일 수 있습니다.

require 'set'

VOWELS = 'aeiou'.each_char.to_set
  #<Set: {"a", "e", "i", "o", "u"}>

이제 나머지 메서드를 shove_vowels_to_end다음 과 같이 작성할 수 있습니다 .

def funky_words(str)
  str.downcase.split.map { |word| shove_vowels_to_end(word) }.join(' ')
end

코드에 대해 논의 할 것이지만 먼저 시도해 보겠습니다.

str = "Little Miss Muffett sat on her tuffet"

funky_words str
  #=> "lttlie mssi mffttue sta no hre tfftue"

알려진 내용에 따라에 대해 str우리는 변경해야 할 수도 있습니다 str.splitstr.strip.split. str.split은와 동일하며 str.split(/\s+/)아마도 적절할 것입니다. String # split을 참조하십시오 .

중간 계산은 다음과 같습니다.

str.downcase.split.map { |word| shove_vowels_to_end(word) }
  #=> ["lttlie", "mssi", "mffttue", "sta", "no", "hre", "tfftue"]

이것이 우리가 .join(' ')마지막에 필요한 이유 입니다.

추가 공백은 유지되지 않습니다.

funky_words "some       spaces"
  #=> "smoe spcsae"

다음은 Ruby와 유사한 글쓰기 방법입니다 shove_vowels_to_end.

def shove_vowels_to_end(word)
  word.each_char.with_object(['', '']) do |char, (non_vowels, vowels)|
     if VOWELS.include?(char)
       vowels << char
     else
       non_vowels << char
     end
  end.join
end

Enumerator # with_object를 참조하십시오 .

블록 변수를 작성할 때 어떻게 배열 분해 를 사용했는지 확인 하십시오.

|char, (non_vowels, vowels)|

을 작성하는 또 다른 방법이 funky_words있습니다. String # gsub 사용 하여 각 비 공백 시퀀스를 수정합니다 .

require 'set'
VOWELS = %w|a e i o u|.to_set
  #=> #<Set: {"a", "e", "i", "o", "u"}>
def funky_words(str)  
  str.downcase.gsub(/[^ ]+/) do |word|
    vowels = ''
    others = ''
    word.each_char do |char|
      if VOWELS.include?(char)
        vowels.prepend(char)
      else
        others.prepend(char)
      end
    end
    others + vowels
  end.reverse
end
str = "Little Miss Muffett sat on her tuffet"
funky_words(str)
  #=> "tfftue hre no sta mffttue mssi lttlie"

단어 수정을 고려하십시오 'muffett'. 될 것 'mffttue'입니다. 내가 마지막에 문자열을 반대하기 때문에, 나는 변환해야 'muffett'하는 'muffett'.reverse #=> 'euttffm'. 이는 다음 단계에서 얻을 수 있습니다.

muffett
vowels = ''
others = 'm'

uffett
vowels = 'u'
others = 'm'

ffett
vowels = 'u'
others = 'fm'

fett
vowels = 'u'
others = 'ffm'

ett
vowels = 'eu'
others = 'ffm

tt
vowels = 'eu'
others = 'tffm'

t
vowels = 'eu'
others = 'ttffm'

vowels + others
  #=> `euttffm`