我的数组中的一些元素是基于用户提交的空字符串。我需要移除这些元素。我有这个:
foreach($linksArray as $link)
{
if($link == '')
{
unset($link);
}
}
print_r($linksArray);
但这并不奏效。$linksArray仍然有空元素。我也尝试过用empty()函数这样做,但结果是一样的。
我的数组中的一些元素是基于用户提交的空字符串。我需要移除这些元素。我有这个:
foreach($linksArray as $link)
{
if($link == '')
{
unset($link);
}
}
print_r($linksArray);
但这并不奏效。$linksArray仍然有空元素。我也尝试过用empty()函数这样做,但结果是一样的。
当前回答
对于这些类型的事情,明确你想要什么和不想要什么要好得多。
它将帮助下一个人不会惊讶于array_filter()没有回调的行为。例如,我以这个问题结束,因为我忘记了array_filter()是否移除NULL。当我可以使用下面的解决方案并得到我的答案时,我浪费了时间。
此外,逻辑是语言无关的,从某种意义上说,代码可以复制到另一种语言,而不必理解php函数(如array_filter)在没有传递回调时的行为。
在我的解决方案中,发生了什么一目了然。删除条件以保留某些内容或添加新条件以过滤其他值。
忽略array_filter()的实际使用,因为我只是传递给它一个自定义回调-如果你想,你可以继续并将其提取到自己的函数中。我只是用它作为一个foreach循环的糖。
<?php
$xs = [0, 1, 2, 3, "0", "", false, null];
$xs = array_filter($xs, function($x) {
if ($x === null) { return false; }
if ($x === false) { return false; }
if ($x === "") { return false; }
if ($x === "0") { return false; }
return true;
});
$xs = array_values($xs); // reindex array
echo "<pre>";
var_export($xs);
这种方法的另一个好处是,您可以将过滤谓词分解为一个抽象函数,该函数可以过滤每个数组的单个值,并构建一个可组合的解决方案。
请参阅此示例和输出的内联注释。
<?php
/**
* @param string $valueToFilter
*
* @return \Closure A function that expects a 1d array and returns an array
* filtered of values matching $valueToFilter.
*/
function filterValue($valueToFilter)
{
return function($xs) use ($valueToFilter) {
return array_filter($xs, function($x) use ($valueToFilter) {
return $x !== $valueToFilter;
});
};
}
// partially applied functions that each expect a 1d array of values
$filterNull = filterValue(null);
$filterFalse = filterValue(false);
$filterZeroString = filterValue("0");
$filterEmptyString = filterValue("");
$xs = [0, 1, 2, 3, null, false, "0", ""];
$xs = $filterNull($xs); //=> [0, 1, 2, 3, false, "0", ""]
$xs = $filterFalse($xs); //=> [0, 1, 2, 3, "0", ""]
$xs = $filterZeroString($xs); //=> [0, 1, 2, 3, ""]
$xs = $filterEmptyString($xs); //=> [0, 1, 2, 3]
echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]
现在,您可以使用pipe()动态地创建一个名为filter()的函数,该函数将为您应用这些部分应用的函数。
<?php
/**
* Supply between 1..n functions each with an arity of 1 (that is, accepts
* one and only one argument). Versions prior to php 5.6 do not have the
* variadic operator `...` and as such require the use of `func_get_args()` to
* obtain the comma-delimited list of expressions provided via the argument
* list on function call.
*
* Example - Call the function `pipe()` like:
*
* pipe ($addOne, $multiplyByTwo);
*
* @return closure
*/
function pipe()
{
$functions = func_get_args(); // an array of callable functions [$addOne, $multiplyByTwo]
return function ($initialAccumulator) use ($functions) { // return a function with an arity of 1
return array_reduce( // chain the supplied `$arg` value through each function in the list of functions
$functions, // an array of functions to reduce over the supplied `$arg` value
function ($accumulator, $currFn) { // the reducer (a reducing function)
return $currFn($accumulator);
},
$initialAccumulator
);
};
}
/**
* @param string $valueToFilter
*
* @return \Closure A function that expects a 1d array and returns an array
* filtered of values matching $valueToFilter.
*/
function filterValue($valueToFilter)
{
return function($xs) use ($valueToFilter) {
return array_filter($xs, function($x) use ($valueToFilter) {
return $x !== $valueToFilter;
});
};
}
$filterer = pipe(
filterValue(null),
filterValue(false),
filterValue("0"),
filterValue("")
);
$xs = [0, 1, 2, 3, null, false, "0", ""];
$xs = $filterer($xs);
echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]
其他回答
当你处理一个字符串数组时,你可以简单地使用array_filter(),它可以方便地为你处理所有这些:
print_r(array_filter($linksArray));
请记住,如果没有提供回调,数组中所有等于FALSE的条目(参见转换为布尔值)将被删除。因此,如果你需要保留精确字符串'0'的元素,你将需要一个自定义回调:
// PHP 7.4 and later
print_r(array_filter($linksArray, fn($value) => !is_null($value) && $value !== ''));
// PHP 5.3 and later
print_r(array_filter($linksArray, function($value) { return !is_null($value) && $value !== ''; }));
// PHP < 5.3
print_r(array_filter($linksArray, create_function('$value', 'return $value !== "";')));
注意:如果你需要在删除空元素后重新索引数组,使用:$linksArray = array_values(array_filter($linksArray));
删除空数组元素
function removeEmptyElements(&$element)
{
if (is_array($element)) {
if ($key = key($element)) {
$element[$key] = array_filter($element);
}
if (count($element) != count($element, COUNT_RECURSIVE)) {
$element = array_filter(current($element), __FUNCTION__);
}
return $element;
} else {
return empty($element) ? false : $element;
}
}
$data = array(
'horarios' => array(),
'grupos' => array(
'1A' => array(
'Juan' => array(
'calificaciones' => array(
'Matematicas' => 8,
'Español' => 5,
'Ingles' => 9,
),
'asistencias' => array(
'enero' => 20,
'febrero' => 10,
'marzo' => '',
)
),
'Damian' => array(
'calificaciones' => array(
'Matematicas' => 10,
'Español' => '',
'Ingles' => 9,
),
'asistencias' => array(
'enero' => 20,
'febrero' => '',
'marzo' => 5,
)
),
),
'1B' => array(
'Mariana' => array(
'calificaciones' => array(
'Matematicas' => null,
'Español' => 7,
'Ingles' => 9,
),
'asistencias' => array(
'enero' => null,
'febrero' => 5,
'marzo' => 5,
)
),
),
)
);
$data = array_filter($data, 'removeEmptyElements');
var_dump($data);
¡它工作!
我必须这样做,以保持(string) 0的数组值
$url = array_filter($data, function ($value) {
return (!empty($value) || $value === 0 || $value==='0');
});
我使用下面的脚本从数组中删除空元素
for ($i=0; $i<$count($Array); $i++)
{
if (empty($Array[$i])) unset($Array[$i]);
}
关于这个话题,最流行的答案是绝对不正确。
考虑下面的PHP脚本:
<?php
$arr = array('1', '', '2', '3', '0');
// Incorrect:
print_r(array_filter($arr));
// Correct:
print_r(array_filter($arr, 'strlen'));
为什么会这样?因为包含单个'0'字符的字符串的计算值也是布尔值false,所以即使它不是空字符串,它仍然会被过滤。那将是一个漏洞。
将内置的strlen函数作为过滤函数传递可以工作,因为它对于非空字符串返回一个非零整数,对于空字符串返回一个零整数。非零整型在转换为布尔型时总是求值为真,而零整型在转换为布尔型时总是求值为假。
所以,绝对的、确定的、正确的答案是:
$arr = array_filter($arr, 'strlen');