ある文字列から特定の文字列を抽出する方法で苦戦しています。
$hoge = #2#1900#3#3000#2#1800
このような文字列あり、#2が何回来ているか、また#2のあとの1900と1800を合計した値を取得したいと思っています。
PHP
1$hoge = '#2#1900#3#3000#2#1800'; 2$count = mb_substr_count($hoge,"#2"); //#2が何回あるか 3$fuge = preg_replace('/\#2/' , '' , $hoge); //#2を削除 4$huge = explode('#' , $fuge); // #区切りで配列に格納 5$fuge = array_sum($fuge); //値を合計
このような記述で#2が2回、3700(1900+1800)と出すことはできました。
ですが、文字列が
$hoge = #2#2000#3#3000#2#1800
このような文字列の際に正しく結果が返ってきません。。。
おそらく#2000の#2にもヒットしている感じがしていません。
$count = mb_substr_count($hoge,"#2");
この2つめの引数に、#2の一桁みたいな指定をすればいいんでしょうか。ご教授の頂きたいです...
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
"#2"が連続するケースについて以下4通りの方法が考えられますので、それぞれ実装してみました。
お望みのものを採用して下さい。
ケース1. 回数にも合計にも含める。
"#2#2#3000"は、"#2"が2回、合計が3002とみなす。
"#2#2#2#4000"は、"#2"が3回、合計が4004とみなす。
ケース2. 回数または合計のどちらか一方だけに含める。
"#2#2#3000"は、"#2"が1回、合計が2とみなす。
"#2#2#2#4000"は、"#2"が2回、合計が4002とみなす。
ケース3. 回数には含めるが、合計には含めない。
"#2#2#3000"は、"#2"が2回、合計が3000とみなす。
"#2#2#2#4000"は、"#2"が3回、合計が4000とみなす。
ケース4. 回数にも合計にも含めない。
"#2#2#3000"は、"#2"が1回、合計が3000とみなす。
"#2#2#2#4000"は、"#2"が1回、合計が4000とみなす。
php
1$array = array( 2 '#2#1900#3#3000#2#1800', 3 '#2#2000#3#3000#2#1800', 4 '#2#2#3000', 5 '#2#2#2#4000' 6); 7 8print "Case 1\n"; 9foreach($array as $text) { 10 $result = case1($text); 11 print " text = $text, count = " . $result[0] . ', sum = ' . $result[1] . "\n"; 12} 13 14print "\nCase 2\n"; 15foreach($array as $text) { 16 $result = case2($text); 17 print " text = $text, count = " . $result[0] . ', sum = ' . $result[1] . "\n"; 18} 19 20print "\nCase 3\n"; 21foreach($array as $text) { 22 $result = case3($text); 23 print " text = $text, count = " . $result[0] . ', sum = ' . $result[1] . "\n"; 24} 25 26print "\nCase 4\n"; 27foreach($array as $text) { 28 $result = case4($text); 29 print " text = $text, count = " . $result[0] . ', sum = ' . $result[1] . "\n"; 30} 31 32function case1($text) { 33 if (preg_match_all('/#2(?=#(\d+))/', $text, $matched) !== FALSE) { 34 return array(count($matched[0]), array_sum($matched[1])); 35 } 36} 37 38function case2($text) { 39 if (preg_match_all('/#2#(\d+)/', $text, $matched) !== FALSE) { 40 return array(count($matched[0]), array_sum($matched[1])); 41 } 42} 43 44function case3($text) { 45 if (preg_match_all('/((?:#2)+)#(\d+)/', $text, $matched) !== FALSE) { 46 $countOfSharp2 = 0; 47 foreach ($matched[1] as $match) { 48 $countOfSharp2 += substr_count($match, '#2'); 49 } 50 return array($countOfSharp2, array_sum($matched[2])); 51 } 52} 53 54function case4($text) { 55 if (preg_match_all('/(?:#2)+#(\d+)/', $text, $matched) !== FALSE) { 56 return array(count($matched[0]), array_sum($matched[1])); 57 } 58}
実行結果
Case 1 text = #2#1900#3#3000#2#1800, count = 2, sum = 3700 text = #2#2000#3#3000#2#1800, count = 2, sum = 3800 text = #2#2#3000, count = 2, sum = 3002 text = #2#2#2#4000, count = 3, sum = 4004 Case 2 text = #2#1900#3#3000#2#1800, count = 2, sum = 3700 text = #2#2000#3#3000#2#1800, count = 2, sum = 3800 text = #2#2#3000, count = 1, sum = 2 text = #2#2#2#4000, count = 2, sum = 4002 Case 3 text = #2#1900#3#3000#2#1800, count = 2, sum = 3700 text = #2#2000#3#3000#2#1800, count = 2, sum = 3800 text = #2#2#3000, count = 2, sum = 3000 text = #2#2#2#4000, count = 3, sum = 4000 Case 4 text = #2#1900#3#3000#2#1800, count = 2, sum = 3700 text = #2#2000#3#3000#2#1800, count = 2, sum = 3800 text = #2#2#3000, count = 1, sum = 3000 text = #2#2#2#4000, count = 1, sum = 4000
投稿2015/10/12 09:06
総合スコア4791
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2015/10/13 12:11
0
特定の文字列を区切りとして切り出して配列にする関数があるので,それで文字列を区切ってfor文で2が一文字のデータがあればカウントを増やしそれ以外は合計していくように関数を組むと楽だと思います。
php
1$COUNTER_TWO=0 2$SUM=0 3$TEMP_STR="#2#1800..." 4$TEMP_STR=preg_split("/[#]/",$TEMP_STR); 5for($i=0;i<count($TEMP_STR);$i++){ 6if($TEMP_STR[$i++]=="2"){ 7$COUNTER_TWO++; 8 if($TEMP_STR[$i]=="1800"||$TEMP_STR[$i]=="2000"){ 9 $SUM+=$TEMP_STR[$i] 10 } 11}else 12{ 13//他に条件があれば 14} 15}
出力部の追加やエラーや処理間違いは適宣修正していただければと思います。
投稿2015/10/12 03:52
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
修正しました。
正規表現で以下のようなパターンを探せば、#2#の後ろに続く数字列を取得できます。
(?<=#2#)([0-9]*)
phpではpreg_match_allという関数を用いれば、繰り返しマッチする文字列を取得できそうです。
以下にphpコードを載せます。
php
1<!DOCTYPE html> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> 5<title>PHPテスト</title> 6</head> 7<body> 8<p> 9<?php 10$subject = "#2#2000#3#3000#2#1800"; 11$pattern = '/(?<=#2#)([0-9]*)/'; 12preg_match_all($pattern, $subject, $matches); 13 14echo count($matches[0])." "; 15echo $matches[0][0]." "; 16echo $matches[0][1]." "; 17?> 18</p> 19 20</body> 21</html>
なぜ$matchesが多次元配列になるのかはわかりませんが(ご存知の方教えてください!)、
$matches[0]も$matches[1]も同じ値が入っていました。
(実行結果) 2 2000 1800
投稿2015/10/12 03:40
編集2015/10/12 04:07総合スコア419
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
お書きのプログラムでお書きの結果は得られないと思います。コピペ間違いでしょうか。
配列に分解してから、順番に見ていくのがいいかと。
PHP
1$str = '#2#2000#3#3000#2#1800'; 2 3$arr = explode('#', $str); // #区切りで配列に格納 4 5$count = 0; 6$sum = 0; 7for($i=0;$i<count($arr);$i++){ 8 if($arr[$i]=='2'){ 9 $count++; 10 $i++; 11 $sum += $arr[$i]; 12 } 13}
投稿2015/10/12 03:40
総合スコア84555
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2015/10/13 12:11
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。