Ruby :: Reversing a string by words or characters
Posted by PunNeng, Thu Feb 08 00:28:00 UTC 2007
คราวนี้ เราต้องการจะทำการเรียกย้อนกลับประโยค ทั้งในรูปแบบของคำและและตัวอักษร อันนี้ไม่ยาก เข้าใจง่าย โดยเราจะใช้ reverse method ในการ return ค่าที่เรียงเสร็จแล้ว แต่ string น้ันๆ ยังไม่เปลี่ียน แต่ถ้าต้องการให้ string นั้นๆ เปลี่ยนไปเลย ให้ใช้ reverse! method แทน
s = ".sdrawkcab si gnirts sihT" s.reverse # => "This string is backwards." s # => ".sdrawkcab si gnirts sihT" s.reverse! # => "This string is backwards." s # => "This string is backwards." |
แต่ถ้าเราต้องการทำในรูปของคำล่ะ มาดูแบบนี้
s = "order. wrong the in are words These" s.split(/(\s+)/).reverse!.join('') # => "These words are in the wrong order." s.split(/\b/).reverse!.join('') # => "These words are in the wrong. order" |
มาดูกัน String#split method จะรับ regular expression เข้ามาเพื่อทำการแยก string ออก แล้วค่อย return ออกมาเป็น array ของชุดที่ถูกแยกออกนั้น
ในส่วนของ regular expression ที่รับมาน้ัน คือ /(\s+)/ คือ เอาตัวที่เป็น white space ที่ติดกันมากกว่า 1 ตัวขึ้นไป ซึ่งหมายความว่าจะใช้ white space เป็นตัวแยก string ออกมา ซึ่ง white space นี จะต้องมีตั้งแต่ 1 ตัว หรือมากกว่าน้ันที่ติดๆ กัน ลองเข้า irb ดู แล้วพิมพ์ว่า
s = "order. wrong the in are words These" s.split(/(s+)/) # => ["order.", " ", "wrong", " ", "the", " ", "in", " ", "are", " ", "word", " ", "These"] |
แต่ \b น้ัน หมายความว่า เอาที่เป็นขอบของคำ เพราะฉะน้ัน มันจะรวมพวกเครื่องหมายหรือสัญลักษณ์ต่างๆ มาด้วย ซึ่งหมายความว่า ใช้ขอบของคำ ซึ่งในที่นี้ ขอบของคำก็จะเป็นสิ่งที่อยู่ระหว่างคำ ซึ่งก็อาจจะรวมพวกเครื่องหมายต่างๆ เข้ามาด้วย ถ้ามันมี เป็นตัวแยก string ออกมา ลองพิมพ์ใน irb ต่อ จะได้
s.split(/\b/) # => ["order", ". ", "wrong", " ", "the", " ", "in", " ", "are", " ", "word", " ", "These"] |
พอได้แล้ว ก็เอามาทำการเรียงประโยคมาใหม่ แล้ว join กัน เอา array ที่ได้มา มา join กันให้เป็นประโยค แล้วทำไมต้อง join ด้วย '' ด้วย ก็เพราะว่าเรามี white space ในชุด array ของเราแล้ว
มีข้อสังเกตอยู่นิดนึง สำหรับ String#split ในกรณีนี้ ถ้าใน regular expression ของเราที่เราจะไว้เป็นตัวแยก อยู่ในวงเล็บ "()" เช่น /(\s*)/ อันนี้ มันจะรวมตัวแยกไปอยู่ใน array ด้วย ลองดูข้อแตกต่างของสองตัวอย่างนี้ครับ
"Three little words".split(/\s+/) # => ["Three", "little", "words"] "Three little words".split(/(\s+)/) # => ["Three", " ", "little", " ", "words"] |
ปล. ผมเกลียด regular expression ไว้จะมาเจอกับมันเต็มๆ อีกที หึหึ
แก้ไขล่าสุด วันที่ 31 กรกฏาคม 2550 เวลา 1.12 น.