我正在使用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)";
我不期待完整的代码,但不知道可以做什么策略。我想这个程序是
但这些在实践中不应该是三个不同的步骤。
答案 0 :(得分:1)
您可以使用preg_replace_callback
匹配括号中的数字,然后使用explode
和array_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)"
答案 1 :(得分: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)
此函数用“ - ”标记两个数字范围,尽管您的示例实际上用逗号分隔两个数字范围。