Как я могу взорвать массив, пропуская пустые элементы массива?

96

Perl join()игнорирует (пропускает) значения пустого массива; PHP implode()не похоже.

Предположим, у меня есть массив:

$array = array('one', '', '', 'four', '', 'six');
implode('-', $array);

дает:

one---four--six

вместо (ИМХО предпочтительнее):

one-four-six

Есть ли другие встроенные модули с тем поведением, которое я ищу? Или это будет заказная работа?

Том Аугер
источник
2
Вы ошибаетесь насчет поведения Perl. joinне пропускает неопределенные элементы. Фактически, они приводят к предупреждению. $a[0]="a"; $a[2]="c"; say join "-",@a;отображает Use of uninitialized value within @a in join or stringи a--c. Можно использовать join '-', grep !defined, ...для пропуска неопределенных значений. grep !length,будет делать пустые строки.
ikegami

Ответы:

212

Вы можете использовать array_filter():

Если обратный вызов не предоставлен, все записи ввода, равные FALSE(см. Преобразование в логическое значение ), будут удалены.

implode('-', array_filter($array));

Очевидно, это не сработает, если у вас есть 0(или любое другое значение, которое оценивается false) в вашем массиве, и вы хотите его сохранить. Но тогда вы можете предоставить свою собственную функцию обратного вызова.

Феликс Клинг
источник
5
Будет ли это , что falseи 0также выброшены?
Бен
1
@maz: Да, но вы всегда можете предоставить свой обратный вызов. empty, когда вы его используете, также будет обрабатывать 0и falseкак false(и удалять), кстати.
Феликс Клинг
3
+1, но это должно быть сказано, что с array_filter()помощью фильтров по умолчанию выключено каждый false, nullпустая строка ( «») и 0.
Tadeck
1
@Tadeck: Да, просто перейдите по ссылке в цитате. Еще больше значений рассматриваются как false: пустой массив, 0.0и "0".
Феликс Клинг
@Felix: Я знал это - просто хотел подчеркнуть это для
новичков
9

Я полагаю, вы не можете считать его встроенным (потому что функция работает с пользовательской функцией), но вы всегда можете использовать array_filter .
Что-то типа:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Бен
источник
1
Использование emptyимеет тот же эффект, что и полное отсутствие обратного вызова. Изменить: вы должны отрицать возвращаемое значение. В противном случае будут возвращены только пустые элементы;) (на самом деле использование, emptyкак вы делали раньше, тоже было неправильным)
Феликс Клинг
1
Да, это назад. Но вы дали мне правильную идеюimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Том Аугер
3

Как вы должны реализовать свой фильтр, зависит только от того, что вы видите «пустым».

function my_filter($item)
{
    return !empty($item); // Will discard 0, 0.0, '0', '', NULL, array() of FALSE
    // Or...
    return !is_null($item); // Will only discard NULL
    // or...
    return $item != "" && $item !== NULL; // Discards empty strings and NULL
    // or... whatever test you feel like doing
}

function my_join($array)
{
    return implode('-',array_filter($array,"my_filter"));
} 
Томас Хупкенс
источник
3

Для того, чтобы удалить null, false, emptyстрока , но сохранить 0и т.д. использовать FUNC. ' strlen'

$arr = [null, false, "", 0, "0", "1", "2", "false"];
print_r(array_filter($arr, 'strlen'));

выведет:

//Array ( [3] => 0 [4] => 0 [5] => 1 [6] => 2 [7] => false )
Али Варли
источник
1

Основываясь на том, что я могу найти, я бы сказал, что, скорее всего, на самом деле нет никакого способа использовать для этого встроенный PHP. Но вы, вероятно, могли бы сделать что-то вроде этого:

function implode_skip_empty($glue,$arr) {
      $ret = "";
      $len = sizeof($arr);
      for($i=0;$i<$len;$i++) {
          $val = $arr[$i];    
          if($val == "") {
              continue;
          } else {
            $ret .= $arr.($i+1==$len)?"":$glue;
          }
      }
      return $ret;
}
оззмотик
источник
1

Попробуй это:

$result = array();

foreach($array as $row) { 
   if ($row != '') {
   array_push($result, $row); 
   }
}

implode('-', $result);
Джереми
источник
1
$array = ["one", NULL, "two", NULL, "three"];
$string = implode("-", array_diff($array, [NULL]));
echo $string;

Возврат one-two-three

Райан Прескотт
источник
-1

array_fileter() кажется здесь принятым способом и, вероятно, все еще самым надежным ответом.

Однако следующее также будет работать, если вы можете гарантировать, что символ «клея» еще не существует в строках каждого элемента массива (что было бы задано в большинстве практических обстоятельств - иначе вы не сможете различить клей из реальных данных в массиве):

$array = array('one', '', '', 'four', '', 'six');
$str   = implode('-', $array);
$str   = preg_replace ('/(-)+/', '\1', $str);
телега
источник
-3

Попробуй это:

if(isset($array))  $array = implode(",", (array)$array);
user2775080
источник
Вы можете использовать isset () для предотвращения предупреждений.
user2775080 02
Я не уверен, как isset()или приведение входного массива в соответствие с arrayлюбыми проблемами исходного сообщения?
Tom Auger
1
Это не выход. Приведение к (массиву) не удаляет пустые элементы из массива.
mjwunderlich