ผมมีไฟล์ประมาณ 40,000 ไฟล์ โดยชื่อไฟล์
best_H1_M1_S1.out
best_H1_M1_S1.out
.
.
.
best_H1_M400_S10.out
โดยชื่อไฟล์ถูกเก็บเป็น list ไว้ในไฟล์ชื่อ filelists.txt
แต่ผมต้องการให้โปรแกรมอ่านชื่อไฟล์เมื่อเจอ _H, _M, _S ให้เอาตัวเลขข้างหลังมาครับ
ผลลัพธ์จะได้ประมาณนี้
H = 1,2,3,4,5
M = 2,2,2,2,2
S = 3,4,5,6,7
ขอคำแนะนำด้วยครับ
ขอบคุณครับ
ถ้าเป็น php นะ trim เอา
itpcc Thu, 22/11/2012 - 15:51
ถ้าเป็น php นะ
ซับซ้อนนิดนึง แต่คงจะใช้ได้นะครับ ท่านผู้รู้ที่มีความคิดเจ๋งกว่าก็แนะนำดูนะครับ ^^
code คงประมาณนี้
ปล.เพิ่มการ substr เข้ามาครับ เพิ่งเห็น -_-"
<?php
EThaiZone Thu, 22/11/2012 - 14:43
{syntaxhighlighter PHP}<?php
$file="filelists.txt";
$hour=$min=$sec=array();
$file_array=file($file);//อ่านไฟล์เข้ามา
foreach ($file_array as $line) {//อ่านทีละบรรทัด
//best_H1_M1_S1.out
if(preg_match('#best_H([0-9]+)_M([0-9]+)_S([0-9]+)#', $line, $matches))
{
//print_r($matches);
$hour[] = $matches[1];
$min[] = $matches[2];
$sec[] = $matches[3];
}
}
unset($file_array); //ล้างที่คืน จะได้ไม่เป็นภาระของลูกหลาน...
echo 'H = '.implode(',', $hour).'\n';
echo 'M = '.implode(',', $min).'\n';
echo 'S = '.implode(',', $sec).'\n';
unset($hour); unset($min); unset($sec); //ล้างที่คืน จะได้ไม่เป็นภาระของลูกหลาน...
?>{/syntaxhighlighter}
มั่นใจว่า regex เขียนไม่ผิด แต่หวังว่า $matches ผมจะเขียนอ้างอิงถูก ถ้าใช่ไม่ได้ลองเอาคอมเมนต์ print_r ออกดูค่าเองละกัน
Array ( [0] =>
itpcc Thu, 22/11/2012 - 15:29
In reply to <?php by EThaiZone
Array ( [0] => best_H1_M1_S400 [1] => 1 [2] => 1 [3] => 400 )
อา... นี่ผมเพิ่งรู้จักกับ preg_match ไม่นึกว่ามันจะทำอย่างนี้ได้
และก็เรื่องอาเรย์ทบไปได้เรื่อยๆด้วย
ว่าแต่ว่า การใช้ regular expression ไม่ทำให้ช้าลงเมื่อทำงานกับงานขนาดใหญ่เหรอครับ?
regex จะช้าลงกับ data
EThaiZone Thu, 22/11/2012 - 16:11
In reply to Array ( [0] => by itpcc
regex จะช้าลงกับ data ขนาดใหญ่ครับ ถ้ามีการซอยเป็น array ก็ถือว่าไวขึ้นหน่อย
จริงๆ ผมสามารถเขียนให้สั้นกว่านี้ด้วย preg_match_all แต่มันก็จะช้าลงอีก
ถ้าเทียบกับแบบที่คุณเขียนมา ยอมรับว่าของผมช้ากว่า แต่ช้าในระดับมิลลิวินาที
แต่ถามกับงานขนาดใหญ่ ผมยังว่าคุ้มที่จะใช้ เพราะการเขียนแยกเทียบดิบๆ ลองมองว่าถ้า string ที่ใช้ค้นไม่ได้ขึ้นต้นด้วยคำว่า best คำนี้ขนาดไม่ตายตัว พอเทียบกับการปรับโค้ดแล้ว มันเสียเวลาตรงนี้เยอะกว่าครับ
แล้วยังมีกรณีที่เราสามารถใช้วิธีอื่นช่วยเพิ่มความเร็วได้ เช่น การเก็บแคชหลังการ parse ข้อมูลแล้ว โดยอิงการเปลี่ยนแปลงของตัว filelists.txt เอง ซึ่งเราไม่มีความจำเป็นต้อง parse ทุกครั้งที่ request แต่ parse เมื่อ filelists.txt มันไม่เหมือนเดิมก็ได้ เมื่อคิดแบบนี้ ความต่างเรื่องวิธีการเขียนตรงนี้ก็ไม่ต้องกังวล เพราะการทำแคชมันช่วยได้
--- จากนี้นอกประเด็นนิด ---
ถ้าลองเคยเขียนระบบใหญ่จริงๆ จะพบครับว่าอย่าไปกังวลปัญหาจุกจิกพวกนี้ ถ้ามีเวลาพอและระบบเสถียรจริง เราค่อยมาปรับโค้ดที่หลังก็ได้ แต่ก็ดูความจำเป็น กับความเป็นไปได้ด้วย
ในบางกรณี แม้ผมจะเขียน php คล่อง แต่บางกรณีภาษาอื่นทำงานได้ไวกว่า แล้ว php มันถึงเพดานของมัน ผมจะเลือกไปใช้ภาษาอื่นหรือระบบอื่นที่ไวกว่านี้ดีกว่า ซึ่งมันไม่ยากเลยในการศึกษา ขอแค่หาเว็บที่สอน best practice เจอ การจะย้ายงานไปบนระบบที่เบากว่าก็ไม่ใช่เรื่องยาก อย่างเช่นการทำ notification ก็เลี่ยงไปใช้ nodejs แทน ก็เบาโข และเราไม่ได้ย้ายงานทั้งหมดไป แต่ใช้ส่วนเดียว ที่เหลือก็ api ยิงกันไปมาภายใน
//กระอักเลือดไปสองสามหยด อ่า
itpcc Thu, 22/11/2012 - 16:54
In reply to regex จะช้าลงกับ data by EThaiZone
//กระอักเลือดไปสองสามหยด
อ่า ครับ ถือเป็นความรู้ใหม่เลย
ผมเองที่ผ่านมาเขียนสดตลอดเลย...(ถึงจะเป็นแค่เด็ก ม.5 ทำโปรเจกเล็กๆมาไม่เยอะก็เหอะ)
ตอนนี้ก็ศึกษา PHP Framework อยู่ ถือเป็นคำแนะนำที่ดี ขอบคุณมากครับ ^^
โอกาสยังมีอีกยาว
EThaiZone Thu, 22/11/2012 - 17:05
In reply to //กระอักเลือดไปสองสามหยด อ่า by itpcc
โอกาสยังมีอีกยาว ผมก็เริ่มเขียน PHP ตอนปวช.เหมือนกัน แต่กว่าผมจะจับ Framework ก็ช่วงเรียนป.ตรี ส่วนหนึ่งเพราะรู้ว่าถ้า OOP ไม่แม่น มันจะล่มเอา
แบบสั้นๆ
EThaiZone Thu, 22/11/2012 - 16:25
แบบสั้นๆ (ฟังค์ชั่นเหล่านี้มันมากับ PHP มีก็ใช้มันเลย)
แบบโครตสั้น (เขียนแล้วเข้าใจทีเดียว อีก 1 เดือนมาดูอีกมีงง)
ตัดเอาแบบสั้นๆนะครับ import
kowito Thu, 22/11/2012 - 16:46
ตัดเอาแบบสั้นๆนะครับ
import collections def split_by_underscore(text): return str.split(text[5:13],'_') #สมมุติว่าอ่านไฟล์มาเป็น list แล้ว a = ['best_H1_M1_S1.out', 'best_H1_M1_S2.out', 'best_H1_M1_S2.out'] print collections.Counter(sum(map(split_by_underscore,a),[]))กรรม อ่านโจทย์ผิด เดี๋ยวดึกๆมาแก้เพิ่ม
ถ้าเป็น file processing
neizod Thu, 22/11/2012 - 18:42
ถ้าเป็น file processing แนะนำทำผ่าน shell script มากกว่า
ls -1 | sed 's/best//;s/\.out//;s/_./ /g' | awk 'BEGIN{ c[1]="H="; c[2]="M="; c[3]="S=" } { for (i in c) c[i] = c[i] $i "," } END{ for (i in c) print c[i] }'