JavaScript ตัด string แบบเนียนๆ

ช่วงที่ผ่านมามีโจทย์นึงจากลูกค้าให้ช่วยหา logic ตัด string แบบที่เขาต้องการบน JavaScript ให้หน่อย โดยเจ้า JavaScript ของผมเนี่ยเป็น mvc api ที่จะส่งข้อมูลลงมาจะเป็น string ที่มี tag span html ปนอยู่ใน string ด้วย (back end เป็นตัวใส่ให้) เพื่อที่จะเป็นจุดอ้างอิงให้ลูกค้าเอาใช้กำหนดใน css ของเขาครับ

HTML SPAN ที่ส่งมาจะมี class (ชื่อสมมติ) ดังนี้ ‘Highlight’, ‘Foo’ และ ‘Bar’สำหรับ class ‘Highlight’ นี่จะผสมกับ class อื่นได้ แต่จะอยู่ลำดับหลังเสมอเช่น หรือ จะไม่มี class=’Highlight Bar’ เด็ดขาด ในแต่ละ string จะมี span tag โผล่มากี่ตัวก็ได้ ไม่จำกัด

สิ่งที่ลูกค้าต้องการ: ลูกค้าต้องการให้ตัด span ที่มี class ‘Foo’ และ ‘Bar’ รวมไปถึงทุกอย่างที่อยู่ใน span tag ของมันออกให้หมด แต่ span ที่มี class ‘Highlight’ ไม่ต้องยุ่งกับมัน เช่น

Input:

Time Warner Cable Reports Development of <span class='Bar Highlight'>AAA</span> First IP Set-Top Box, Sees Boxes <span class='Bar'>CATTT</span> in Select Markets by Year End  
<span class='Foo'>GE.N</span>  <span class='Foo'>TWC.N</span> <span class='Bar'>Hello</span>

Output:

Time Warner Cable Reports Development of <span class='Bar Highlight'>AAA</span> First IP Set-Top Box, Sees Boxes in Select Markets by Year End

Code แรกที่ผมทำนั้นเน้นให้ logic ถูก ทำงานได้ ยังไม่ได้คิดถึงเรื่อง Performance อะไรนัก เอาแบบวน loop recursive ถึกๆ แล้วหา string ด้วย indexOf แล้วตัดด้วย replace กันดื้อๆ เลย แบบนี้ครับ (gen มาจาก CoffeeScript นะ)

var arrayTag, filterTag, msgBase, removeTag, tagBar, tagFoo, tagSPAN;

tagBar = "<span class='Bar'>";
tagFoo = "<span class='Foo'>";
tagSPAN = "</span>";

arrayTag = [tagQuoteRef, tagStoryRef, tagNewsSearchID, tagNewsSearch];

msgBase = "Time Warner Cable Reports Development of <span class='Bar Highlight'>AAA</span> First IP Set-Top Box, Sees Boxes <span class='Foo'>CATTT</span> in Select <span class='Foo Highlight'>Maeooooo</span> Markets by Year End  <span class=Bar'>GE.N</span>  <span class='Bar'>TWC.N</span> <span class='Foo'>Hello</span> ";

filterTag = function(msgStr, filterStr, index) {
	var indexSpan, indexStart;
    	indexStart = -1;
	indexSpan = -1;
   	tmp = "";
    	indexStart = msgStr.indexOf(filterStr, index);
    	if (indexStart !== -1) {
      		indexSpan = msgStr.indexOf(tagSPAN, indexStart);
      		msgStr = msgStr.replace(msgStr.slice(indexStart, indexSpan + 7), '');
      		return filterTag(msgStr, filterStr, indexSpan + 8);
    	} else {
      		return msgStr;
	}
};

removeTag = function(msgStr) {
	var tagRemove, _i, _len;
    	console.log("Orignal Text: " + msgStr);
    	for (_i = 0, _len = arrayTag.length; _i < _len; _i++) {
      		tagRemove = arrayTag[_i];
      		msgStr = filterTag(msgStr, tagRemove, 0);
    	}
    	console.log("Remove Text: " + msgStr);
};

removeTag(msgBase);

รองรันๆ แล้วก็โอเค ไม่มีหลุดอะไร แต่ส่วนตัวคิดว่าถ้ามันเขียนด้วย Regular expression น่าจะเนียนกว่านี้ แต่ผมเขียนไม่เป็น เลยลองไปถาม @neizod ดู ซึ่งเนยซดก็ตอบว่า code ก็โอเคแหละ แต่ถ้าคิดถึง performance น่าจะลองแบบนี้นะครับ

msgBase =msgStr.split(/<span class='(?:Foo|Bar)'>.*?<\/span>/).join('')

เขร้ code แม่มสั้นสัดๆ ลองเทสด้วย เวบ jsperf แล้วเร็วโคตรๆ ผมก็เลยส่งอันนี้ให้ Dev ทีมผม review ดู น้องเขาก็เอาไป review สักพักแล้วก็บอกว่าอันนี้น่าจะเร็วกว่านะ

msgBase = msgStr.replace(/<span class='(Foo|Bar)'>.*?<\/span>/g,'');

ซึ่งผลก็ออกมา เร็วขึ้นเยอะ เลย \ w / ซึ่งผมก็เอาอันนี้แหละไปบอกลูกค้าอีกที

สรุป:

  • ความรู้และความเข้าใจเรื่อง Regular expression ถือว่าสำคัญมาก ซึ่งผมดันไม่รู้เลย
  • การได้เห็น code ดีๆ มันเปิดหูเปิดตาเราได้เยอะเลย

กุฎีจีนไซด์โปรเจค (Kadeejeen Side Project) #1: วัดอรุณ

ถึง entry ชุดกุฎีจีนโปรเจคจะจบไปแล้ว แต่ก็ยังเหลือสถานที่อื่นๆ ที่ผมเก็บภาพมาระหว่างเดินทางจากบ้านไปย่านกุฏีจีนก็เลยแยกภาพชุดนั้นออกมาเป็น “กุฎีจีนไซด์โปรเจค” ครับ

ขอเริ่มที่แรกที่วัดอรุณราชวรารามราชวรมหาวิหาร ครับ ที่นี่เป็นที่ที่ยังไงก็ต้องผ่านอยู่แล้วทุกครั้งที่ไปถ่ายรูปแถวๆ ย่านกุฏีจีน วัดอรุณผมมาถ่ายรูปหลายรอบแล้ว รอบนี้ผมเลยเก็บไว้ถ่ายตอนขากลับหรือไม่ก็หามุมที่ไม่เคยถ่ายมาก่อนครับ (ยกเว้นมุมมหาชนนะ)


มุมมหาชน 1


มุมมหาชน 2

วันแรกที่เดินเข้าไปทะลุหลังวัดไปเจอทีมช่างกำลังบูรณะรูปปั้นต่างๆ (รวมไปถึงสร้างตัวใหม่ด้วย)


Continue reading “กุฎีจีนไซด์โปรเจค (Kadeejeen Side Project) #1: วัดอรุณ”

อะไรก็ได้

ผมเพิ่งพบว่าเวลาถามความเห็นกัน ความเห็นที่ว่า “อะไรก็ได้” นี่แม่งไม่มีค่าที่สุดแล้วในบรรดาความเห็นทั้งหมด

คือถ้าความเห็นอื่นๆ มันเทไปทางเดียวกันซะเยอะ อะไรก็ได้นี่อาจจะไม่เป็นปัญหา ซึ่งมันก็มีโอกาสน้อยมาก พอความเห็นมันกระจายนี่ไอ้ “อะไรก็ได้นี่” นี่ไม่ทำให้ได้ข้อสรุปห่าอะไรเลยครับ

ที่ระยำที่สุดคืออะไรก็ได้มันไม่เคยเป็นอะไรก็ได้จริงๆ เลยสักครั้ง ชื่อเต็มๆ มันคือ “อะไรก็ได้ที่ถูกใจกู” หรือ “อะไรก็ได้ แต่…” แล้วแม่งก็บอกเงื่อนไขลอยๆ มาหรือไม่ก็ไม่บอกเงื่อนไขห่าไรมา ให้เรามโนกันเอง สุดท้ายกลายเป็นไม่เสนอความเห็นแต่เสือกปฏิเสธิแม่งทุกความเห็นที่ไม่ถูกใจตัวเองซะงั้น

ใครมีวิธีแก้ “อะไรก็ได้” มาแนะนำบ้างไหม?