2016-06-16 7 views
0

私はPHPでテキストを処理し、連続番号を括弧内の数字を見つけて、マージする必要があり、そのような私は完全なコードを期待していない 文字列内の連続番号を見つけてマージする方法は?

$raw = "outside 1,2,3,11,12,13 (5,6,11,12,13,14,16,19,20,21)"; 

$result = "outside 1,2,3,11,12,13 (5,6,11-14,16,19-21)"; 

として、しかし行うための戦略であることができるか見当もつかないしていますそう。私はその手順は次のようなものだと推測します。

  1. 括弧内の数字の検索(正規表現による)。
  2. 次に、番号が連続しているかどうかを確認します。
  3. 次に、一致するものを置き換えます。

しかし、これらは実際には3つの異なるステップであってはなりません。

+2

「3」と「11」は「外部」からどこに来ますか? – ClasG

+0

あなたは範囲のことをする方法を参照してください:http://stackoverflow.com/q/33874059/3933332今すぐ正規表現を使用して、このコードを括弧内の数字に適用することができます。 – Rizier123

+0

@ClasG誤字をおかけして申し訳ありません:p – Googlebot

答えて

1

preg_replace_callbackを使用して括弧内の数字と一致させてから、explodearray_mapを使用して整数に変換してソートし、範囲を確認してください。

機能

function fixRange($match) { 
    // Extract the numbers 
    $numbers = array_map('intval', explode(',', $match[1])); 

    // Make sure they're sequential 
    sort($numbers); 

    $count = count($numbers); 

    $replacements = []; 

    for ($i = 0; $i < $count; $i++) { 
     $startNumber = $endNumber = $numbers[$i]; 

     for ($j = $i + 1; $j < $count; $j++) { 
      if ($numbers[$j] === ($endNumber + 1)) { 
       $endNumber = $numbers[$j]; 

       $i = $j; 
      } else { 
       break; 
      } 
     } 

     // Add range if $endNumber is not the same as $startNumber 
     $replacements[] = $startNumber . ($startNumber !== $endNumber ? '-' . $endNumber : ''); 
    } 

    return '(' . implode(',', $replacements) . ')'; 
} 

<?php 

$raw = "outside 1,2,12,13 (5,6,11,12,13,14,16,19,20,21)"; 

$result = preg_replace_callback('~\(([^\)]+)\)~', 'fixRange', $raw); 

var_dump($result); 
// string(38) "outside 1,2,12,13 (5-6,11-14,16,19-21)" 

$raw = "outside 1,2,12,13 (5,6,11,12,13,14,16,19,20,21,22,23,25)"; 

$result = preg_replace_callback('~\(([^\)]+)\)~', 'fixRange', $raw); 

var_dump($result); 
// string(41) "outside 1,2,12,13 (5-6,11-14,16,19-23,25)" 

DEMO

+0

Wonderful、私は 'preg_replace_callback'の有用性を知りました。 – Googlebot

1

読みにくいが、短いだ溶液(それは今までのコードへの正しい方法であるかのように(!))。

$raw = "outside 1,2,3,11,12,13 (5,6,11,12,13,14,16,19,20,21)"; 

// Find sections inside parentheses 
$result = preg_replace_callback("[\(([^\)]+)\)]", function($in_parens){ 
    // Split the numbers - I'm assuming the format is guaranteed to be just digits and 
    // commas. 
    $numbers = explode(",", $in_parens[1]); 
    return "(" . array_reduce($numbers, function($carry, $number) { 
     if (preg_match("[(?:^|[-,])(\d+)$]", $carry, $prev) && $prev[1] == $number - 1) { 
      // If the previous number is one less than the current number: remove 
      // the previous number (if it's the end of the range) and replace it 
      // with "-" followed by this number. 
      return preg_replace("[-\d+$]", "", $carry) . "-$number"; 
     } else { 
      // Otherwise just tack this number on to the previous result with a comma. 
      return ($carry ? "$carry," : "") . $number; 
     } 
    }) . ")"; 
}, $raw); 

var_dump($result); 
//string 'outside 1,2,3,11,12,13 (5-6,11-14,16,19-21)' (length=43) 

この例では、実際には2つの数値範囲をカンマで区切っていますが、この例では2つの数値範囲に " - "を付けています。

関連する問題