【问题标题】:Explode string into array with no empty elements?将字符串分解为没有空元素的数组?
【发布时间】:2010-09-09 00:55:15
【问题描述】:

PHP 的explode 函数返回一个字符串数组,该数组在某些提供的子字符串上拆分。当有前导、尾随或连续分隔符时,它将返回空字符串,如下所示:

var_dump(explode('/', '1/2//3/'));
array(5) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(0) ""
  [3]=>
  string(1) "3"
  [4]=>
  string(0) ""
}

是否有一些不同的函数或选项或任何东西可以返回所有内容除了空字符串?

var_dump(different_explode('/', '1/2//3/'));
array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(1) "3"
}

【问题讨论】:

    标签: php arrays string filtering explode


    【解决方案1】:

    试试preg_split

    $exploded = preg_split('@/@', '1/2//3/', NULL, PREG_SPLIT_NO_EMPTY);

    【讨论】:

    • 我认为这是最正确的,因为它维护了正确的数组索引。
    • @Ryono:你到底是什么意思?
    • preg_split 将返回一个具有顺序数组索引的数组(即 0、1、2、3)。使用 array_filter 的其他一些建议将返回非顺序数组索引,因为某些元素被过滤掉了,剩下的数组索引为 0,1,3,7。
    • @RafikBari 正则表达式模式的第一个字符是它的分隔符。见php.net/manual/en/regexp.reference.delimiters.php。通常使用/,但我在这里使用@,因为/ 在我们的字符串中。
    • 如果唯一的原因是得到一个非空条目的数组,你应该使用比 preg_split 更快的 array_filter(explode()) 选项。
    【解决方案2】:

    array_filter 将删除空白字段,这里是一个没有过滤器的示例:

    print_r(explode('/', '1/2//3/'))
    

    打印:

    Array
    (
        [0] => 1
        [1] => 2
        [2] =>
        [3] => 3
        [4] =>
    )
    

    使用过滤器:

    php> print_r(array_filter(explode('/', '1/2//3/')))
    

    打印:

    Array
    (
        [0] => 1
        [1] => 2
        [3] => 3
    )
    

    您将过滤掉所有解析为“false”的值。

    http://uk.php.net/manual/en/function.array-filter.php

    【讨论】:

    • 这也将删除“0”,因为它在布尔上下文中为假。所以它可能不是你想要的!
    • 为了清楚起见,“否”只是对“是否有一些不同的功能或选项或任何东西”的回答——我可以说“不,没有内置任何东西”更清楚。跨度>
    • 这正是我所需要的。我必须确保一个常量数组总是有四个字符串值,这些值必须从爆炸中获得。但是,如果爆炸失败,我需要在 [0] 处提供一个备用值。我是通过这种方式实现的:array_filter(explode(',',($string, 4))) + ['default_value','','','']。这样,失败的爆炸将不包含任何值,结果将完全是第二个数组。这当然是非正统的,但对于像这样的常量来说,它是一个干净的解决方案。
    【解决方案3】:

    只为多样化:

    array_diff(explode('/', '1/2//3/'), array(''))
    

    这也有效,但与 preg_split 不同,它会弄乱数组索引。有些人可能更喜欢它,而不是必须声明一个回调函数才能使用 array_filter。

    【讨论】:

    • 如果只过滤空字符串等虚假值,则使用 array_filter 时不需要回调函数
    【解决方案4】:
    function not_empty_string($s) {
      return $s !== "";
    }
    
    array_filter(explode('/', '1/2//3/'), 'not_empty_string');
    

    【讨论】:

    • 注意:如果您可能有“1/2//0/3”并希望保留零,这比对 array_filter() 的“裸”调用要好。
    • 好评。我想建议“裸”电话,但是是的,它会抛出零。
    【解决方案5】:

    我在TYPO3中使用过这个,看$onlyNonEmptyValues参数:

    function trimExplode($delim, $string, $onlyNonEmptyValues=0){
        $temp = explode($delim,$string);
        $newtemp=array();
        while(list($key,$val)=each($temp))      {
            if (!$onlyNonEmptyValues || strcmp("",trim($val)))      {
                $newtemp[]=trim($val);
            }
        }
        reset($newtemp);
        return $newtemp;
    }
    

    它不会弄乱索引:

    var_dump(trimExplode('/', '1/2//3/',1));
    

    结果:

    array(3) {
      [0]=>
      string(1) "1"
      [1]=>
      string(1) "2"
      [2]=>
      string(1) "3"
    }
    

    【讨论】:

      【解决方案6】:

      这是一个应该输出新索引数组的解决方案。

      $result = array_deflate( explode( $delim, $array) );
      
      function array_deflate( $arr, $emptyval='' ){
          $ret=[];
          for($i=0,$L=count($arr); $i<$L; ++$i)
              if($arr[$i] !== $emptyval) $ret[]=$arr[$i];
          return $ret;
      }
      

      虽然与其他一些建议非常相似,但此实现具有通用使用的好处。对于具有非字符串元素的数组,提供类型化的空值作为第二个参数。

      array_deflate( $objArray, new stdClass() );

      array_deflate( $databaseArray, NULL );

      array_deflate( $intArray, NULL );

      array_deflate( $arrayArray, [] );

      array_deflate( $assocArrayArray, [''=&gt;NULL] );

      array_deflate( $processedArray, new Exception('processing error') );

      .

      .

      .

      带有可选的过滤器参数..

      function array_deflate( $arr, $trigger='', $filter=NULL, $compare=NULL){
          $ret=[];
          if ($filter === NULL) $filter = function($el) { return $el; };
          if ($compare === NULL) $compare = function($a,$b) { return $a===$b; };
      
          for($i=0,$L=count($arr); $i<$L; ++$i)
              if( !$compare(arr[$i],$trigger) ) $ret[]=$arr[$i];
              else $filter($arr[$i]);
          return $ret;
      }
      

      随着使用..

      function targetHandler($t){ /* .... */ }    
      array_deflate( $haystack, $needle, targetHandler );
      

      将 array_deflate 变成一种处理选择元素并将它们从数组中删除的方法。更好的方法是将 if 语句转换为比较函数,该函数也作为参数传递,以防您觉得奇怪。

      array_inflate 反过来,将一个额外的数组作为第一个参数,匹配被推送到,而不匹配被过滤。

      function array_inflate($dest,$src,$trigger='', $filter=NULL, $compare=NULL){
          if ($filter === NULL) $filter = function($el) { return $el; };
          if ($compare === NULL) $compare = function($a,$b) { return $a===$b; };
      
          for($i=0,$L=count($src); $i<$L; ++$i)
              if( $compare(src[$i],$trigger) ) $dest[]=$src[$i];
              else $filter($src[$i]);
          return $dest;
      }
      

      随着使用..

      $smartppl=[];    
      $smartppl=array_inflate( $smartppl,
                               $allppl,
                               (object)['intelligence'=>110],
                               cureStupid,
                               isSmart);
      
      function isSmart($a,$threshold){
          if( isset($a->intellgence) )    //has intelligence?
              if( isset($threshold->intellgence) )    //has intelligence?
                  if( $a->intelligence >= $threshold->intelligence )
                      return true;
                  else return INVALID_THRESHOLD; //error
              else return INVALID_TARGET; //error
          return false;
      }
      
      function cureStupid($person){
          $dangerous_chemical = selectNeurosteroid();
          applyNeurosteroid($person, $dangerous_chemical);
      
          if( isSmart($person,(object)['intelligence'=>110]) ) 
              return $person;
          else 
              lobotomize($person);
      
          return $person;
      }
      

      从而为世界教育问题提供了一种理想的算法。 Aaand 在我把它改成别的东西之前我会停在那里..

      【讨论】:

        【解决方案7】:

        编写一个包装函数来剥离它们

        function MyExplode($sep, $str)
        {
            $arr = explode($sep, $str);
            foreach($arr as $item)
                if(item != "")
                    $out[] = $item;
            return $out;
        }
        

        【讨论】:

          【解决方案8】:

          我没有在这里测试过其他建议,但这可行:

          function different_explode($mypattern,$mystring){
              $array1 = explode($mypattern,$mystring);
              $retArray = Array();
              foreach($array1 as $myval){
                  if($myval != ''){
                      array_push($retArray,$myval);
                  }
              }
              return $retArray;
          }
          

          【讨论】:

            【解决方案9】:

            使用该函数过滤explode函数的输出

              function filter_empty(&$arrayvar) {
                    $newarray = array();
                    foreach ($arrayvar as $k => $value)
                        if ($value !== "")
                            $newarray[$k] = $value;
            
                    $arrayvar = $newarray;
                }
            

            【讨论】:

            • 如果您将数组作为参考,您是否可以直接取消设置()空字符串索引,而不需要额外的临时数组?
            【解决方案10】:

            正则表达式解决方案往往比基本文本替换慢得多,所以我会用单个分隔符替换双分隔符,修剪任何空格的字符串,然后使用爆炸:

            // assuming $source = '1/2//3/';
            $source = str_replace('//', '/', $source);
            $source = trim($source);
            $parts = explode('/', $source);
            

            【讨论】:

              【解决方案11】:

              没有正则表达式开销 - 应该相当有效,strlen 只计算字节数

              如果您不关心索引,请删除 array_values()

              如果你愿意,可以把它变成函数explode_interesting($array, $fix_index = 0)

              $interesting = array_values( 
                               array_filter(
                                 explode('/', '/1//2//3///4/0/false' ),
                                 function ($val) { return strlen($val); }
                             ));
              
              echo "<pre>", var_export( $interesting, true ), "</pre>";
              

              享受吧,杰夫

              【讨论】:

                【解决方案12】:

                PHP 的split function 类似于explode 函数,只是它允许您输入正则表达式模式作为分隔符。大意是:

                $exploded_arr = split('/\/+/', '1/2//3/');
                

                【讨论】:

                • 从 PHP 5.3.0 开始,该函数已被弃用。强烈建议不要依赖此功能。
                • 改用preg_split
                【解决方案13】:

                我通常将其封装在对array_filter 的调用中,例如

                var_dump(array_filter(explode('/', '1/2//3/'))
                =>
                array(3) {
                  [0]=>
                  string(1) "1"
                  [1]=>
                  string(1) "2"
                  [3]=>
                  string(1) "3"
                }
                

                当然,请注意数组键是被维护的;如果您想要这种行为,请记住向 array_values() 添加一个外包装调用。

                【讨论】:

                • 数组过滤过滤器默认为 FALSE。您需要一个回调函数才能使其工作
                • 呃,Fire Lancer,请阅读文档。 "示例 #2 array_filter() 没有回调"
                • 是的,这取决于您所说的“工作”——请参阅我对 James Aylett 帖子的评论。具有讽刺意味的是,您的版本还将删除原始字符串中出现的“0”。
                • 哦,好吧...我忘记了 php 将空字符串视为 FALSe,尽管它只是 0 和 null
                猜你喜欢
                • 2015-01-27
                • 2021-01-13
                • 2012-02-26
                • 1970-01-01
                • 1970-01-01
                • 2015-01-23
                • 1970-01-01
                • 1970-01-01
                • 2012-07-10
                相关资源
                最近更新 更多