如何在字符串中每隔一个逗号-space 爆炸一次?

How to explode on every second comma-space in a string?

我在一些旧代码中发现了一个错误,希望在 SO 社区的帮助下我可以很快修复它。

用户可以将多个 city/states 插入到一个数组中,因此该数组将如下所示:

 Norfolk, VA, Chicago, IL, New York, NY

我需要保留内部逗号并使用尾随逗号作为分隔符。

当前PHP代码获取数据是这样的:

 $deliveryCityArray = explode(',', $_POST['deliveryCity']);

在网格中显示时,City/State 应在同一列中。

不幸的是,对于我当前的代码,城市将在其自己的单元格中,州将在下一行。

我需要添加什么才能保留尾随逗号但保留内部逗号?

正常分解,然后将生成的数组分成两对,然后遍历这些对并再次内爆

$deliveryCity = 'Norfolk, VA, Chicago, IL, New York, NY';

$deliveryCityArray = array_map(
    function($value) {
        return implode(',', $value);
    },
    array_chunk(
        explode(',', $deliveryCity),
        2
    )
);

Demo

唯一可以做到这一点的方法是做出一些假设 - 只要您确信 'separating' 逗号总是每隔一个逗号,您就可以这样做:

$results = array();
$tmp = explode(",",$_POST['deliveryCity']);
$idx = 0;
while ($idx < count($tmp)){
   $results[] = $tmp[$idx] . "," . $tmp[$idx+1];
   $idx += 2;
}

//$results will contain your resultant array.

您要处理的字符串中有一个 模式:您希望 explode 在 2 个大写字母后的每个逗号上输入。在那种情况下:

$array = preg_split('/(?<=, [A-Z]{2}),/', $str);

工作正常 (DEMO)

工作原理:

  • (?<=:积极的回顾断言。该模式只有在其前面有某个子模式时才会匹配
  • , [A-Z]{2}):子模式:一个逗号,space 和 2 个大写字符(右括号表示后向断言结束)
  • ,:一个乱码,(如果lookbehind 成功则匹配)。该字符被匹配并用于分解字符串。后视是零宽度匹配,因此它不被视为分隔符的一部分

如果整个字符串都是大写,模式需要改变一点,但不会太大(Updated demo):

$array = preg_split('/(?<=,\s[A-Z]{2}\b),/', $upperStr);

我只是添加了一个 \b 到 lookbehind(匹配单词边界的元字符)。无论如何,这个单词边界是可选的,因为我们正在匹配 , [A-Z]{2}, 无论如何。

使用正则表达式时,为获得最佳效率,请避免使用捕获组和环视。通过利用 \K 到 "restart the fullstring match".

,可以在没有这些技术的情况下完成此任务

代码:(Demo)

$string='Norfolk, VA, Chicago, IL, New York, NY';
var_export(preg_split('/[A-Z]{2}\K, /',$string));

输出:

array (
  0 => 'Norfolk, VA',
  1 => 'Chicago, IL',
  2 => 'New York, NY',
)

这个模式有效地说:

  • 寻找缩写状态(两个大写字母)然后
  • 然后重新开始全字符串匹配
  • 使用逗号和space作为分隔符。简单干净。