过滤二维数组,以便从所有行中删除仅包含空值的列

问题描述 投票:0回答:4

我正在寻找一种过滤 PHP 多维数组(它是一个表)的方法。 该数组看起来与此类似:

array (
  0 => 
  array (
    'Standort' => '',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '04.05.2022 11:03',
    'Online' => '',
  ),
  1 => 
  array (
    'Standort' => 'Schweiz',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '11.02.2022 14:59',
    'Online' => '',
  ),
)

数组内的键每次都是相同的。我的目标是循环遍历每个子数组并删除每个子数组中的任何空键。 我已经尝试过这个:

$table_row_array = array_filter(array_map('array_filter', $table_row_array));

但这不是解决方案,因为有时我的表格行没有匹配的键。

预期结果是:

array (
  0 => 
  array (
    'Standort' => '',
    'On-/Offline seit' => '04.05.2022 11:03',
  ),
  1 => 
  array (
    'Standort' => 'Schweiz',
    'On-/Offline seit' => '11.02.2022 14:59',
  ),
)
php arrays multidimensional-array filtering
4个回答
0
投票

循环第一个数组元素的键。对于每个键,使用 array_values 提取该键下的所有值,使它们唯一,然后检查是否只剩下一个,并且它是一个空字符串 - 如果是,则您找到了一个需要删除的键。
然后,循环整个数组,并从各个项目中取消设置这些键。

$data = array (
  0 => 
  array (
    'Standort' => '',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '04.05.2022 11:03',
    'Online' => '',
  ),
  1 => 
  array (
    'Standort' => 'Schweiz',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '11.02.2022 14:59',
    'Online' => '',
  ),
);

$emptyKeys = [];
foreach(array_keys($data[0]) as $key) {
    $uniqueValues = array_unique(array_column($data, $key));
    if(count($uniqueValues) == 1 && $uniqueValues[0] === '') {
        $emptyKeys[] = $key;
    }
}
foreach($emptyKeys as $emptyKey) {
    foreach($data as &$item) { // pass $item by reference here, so that we
                               // manipulate the original array, and not just a copy
        unset($item[$emptyKey]); // remove the key
    }
    unset($item); // unset the reference itself
}

var_dump($data);

您当然也可以嵌套循环,并去掉额外的

$emptyKeys
数组:

foreach(array_keys($data[0]) as $key) {
    $uniqueValues = array_unique(array_column($data, $key));
    if(count($uniqueValues) == 1 && $uniqueValues[0] === '') {
        foreach($data as &$item) {
            unset($item[$key]);
        }
        unset($item);
    }
}

0
投票

使用 array_flip 切换键和值,取消设置为空,仅适用于一个数组中的不同值,因为相似的值将被覆盖:

$laData = array (
  0 => 
  array (
    'Standort' => '',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '04.05.2022 11:03',
    'Online' => '',
  ),
  1 => 
  array (
    'Standort' => 'Schweiz',
    'Letzte Meldung' => '',
    'On-/Offline seit' => '11.02.2022 14:59',
    'Online' => '',
  ),
);

$laResult = array();
foreach($laData as $laSingleData) {
    $laSingleData = array_flip($laSingleData);
    unset($laSingleData['']);
    $laSingleData = array_flip($laSingleData);
    $laResult[] = $laSingleData;
}

print_r($laResult);

0
投票
$input = [
    [
        'Standort'         => '',
        'Letzte Meldung'   => '',
        'On-/Offline seit' => '04.05.2022 11:03',
        'Online'           => '',
    ],
    [
        'Standort'         => 'Schweiz',
        'Letzte Meldung'   => '',
        'On-/Offline seit' => '11.02.2022 14:59',
        'Online'           => '',
    ]
];

$keys = array_filter(
    array_keys($input[0]),
    fn($key) => array_filter(array_column($input, $key), fn($value) => !empty($value))
);

$result = array_map(
    fn($item) => array_values(array_intersect_key($item, array_flip($keys))),
    $input
);

print_r($result);

输出:

Array
(
    [0] => Array
        (
            [0] => 
            [1] => 04.05.2022 11:03
        )

    [1] => Array
        (
            [0] => Schweiz
            [1] => 11.02.2022 14:59
        )

)

0
投票

我不推荐 @FatFreddy 的利用

array_flip()
的方法——这种技术会破坏不应该被破坏的值。

为了添加另一个可行的解决方案,我将展示几个循环——一个用于过滤,一个用于转置。

代码:(演示

$columns = [];
foreach ($input[0] as $columnName => $value) {
    $columnData = array_column($input, $columnName);
    if (strlen(implode($columnData))) {
        $columns[$columnName] = $columnData;
    }
}
$result = [];
foreach ($columns as $colName => $colValues) {
    foreach ($colValues as $i => $value) {
        $result[$i][$colName] = $value;
    }
}
var_export($result);

对于函数式方法,迭代数组中的每个叶节点并收集与任何非空值相关的列名称。然后再次传递输入,以按白名单列名称过滤每行的内容。

代码:(演示

$keep = [];
array_walk_recursive(
    $input,
    function($v, $k) use(&$keep) {
        if (strlen($v)) {
            $keep[$k] = null;
        }
    }
);

var_export(
    $keep ? array_map(fn($row) => array_intersect_key($row, $keep), $input) : []
);
© www.soinside.com 2019 - 2024. All rights reserved.