ย้อนกลับคำย้ายสระและลดทอนทุกอย่าง
ฉันใหม่สำหรับ 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
คำตอบ
One-liners นั้นสนุกดี แต่โลกนี้ไม่ต้องการมันมากกว่านี้ ที่กล่าวว่าพวกเขาไม่จำเป็นต้องอ่านไม่ออก สมองในอนาคตของคุณจะพูดอะไรในอีกหนึ่งปีนับจากนี้หากคุณต้องรักษาการทำงานนั้นไว้
ต่อไปนี้เป็นแนวทางที่แสดงให้เห็นถึงเทคนิคที่สามารถปรับขนาดได้เพื่อให้ "one-liners" ยาว ๆ สามารถอ่านได้โดย (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
โซลูชันของคุณทำสิ่งต่อไปนี้:
- downcase สตริง
- แปลงสตริงผลลัพธ์เป็นอาร์เรย์ของคำ
- ย้อนกลับอาร์เรย์ของคำ
- แปลงคำแต่ละคำในอาร์เรย์เพื่อให้สระอยู่ท้ายสระและลำดับจะถูกเก็บรักษาไว้สำหรับทั้งสระและที่ไม่ใช่สระ
- รวมคำในอาร์เรย์ผลลัพธ์เพื่อสร้างสตริง
เริ่มต้นด้วยการดำเนินการสุดท้าย เพื่อให้โค้ดสามารถอ่านได้มากขึ้นและการทดสอบความเร็วเรามาสร้างวิธีแยกกัน
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 # เข้าร่วม
นอกเหนือ: ฉันสามารถเขียน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.split
เหมือนกับซึ่งน่าจะเหมาะสม ดูString # แยกstr.strip.split
str.split
str.split(/\s+/)
การคำนวณระดับกลางคือ:
str.downcase.split.map { |word| shove_vowels_to_end(word) }
#=> ["lttlie", "mssi", "mffttue", "sta", "no", "hre", "tfftue"]
ซึ่งเป็นเหตุผลที่เราต้องการ.join(' ')
ในตอนท้าย
สังเกตว่าช่องว่างพิเศษจะไม่ถูกเก็บรักษาไว้:
funky_words "some spaces"
#=> "smoe spcsae"
นี่คือวิธีการเขียนที่เหมือนทับทิมมากขึ้น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
ดูแจงนับ # 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`