首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 数组操作工具类 ArrayHelper 全功能详解

     編輯:PHP 綜合知識

类设计目标

提供一组静态方法,覆盖数组清洗、列提取、哈希映射、分组、树形转换、多列排序等高频操作,代码复用率极高,适合作为项目基础库。

完整类代码 (含详细 PHPDoc)

class ArrayHelper {
    /**
     * 递归移除数组中空白元素 (含纯空白字符)
     * @param array $arr 引用传递,原地修改
     * @param bool $trim 是否 trim 非空元素
     */
    public static function removeEmpty(array &$arr, bool $trim = true): void {
        foreach ($arr as $key => $value) {
            if (is_array($value)) {
                self::removeEmpty($arr[$key], $trim);
            } else {
                $value = trim($value);
                if ($value === '') {
                    unset($arr[$key]);
                } elseif ($trim) {
                    $arr[$key] = $value;
                }
            }
        }
    }

    /**
     * 从二维数组提取指定列的所有值
     * @param array $arr 数据源
     * @param string $col 列名
     * @return array 值数组
     */
    public static function getCols(array $arr, string $col): array {
        $ret = [];
        foreach ($arr as $row) {
            if (isset($row[$col])) $ret[] = $row[$col];
        }
        return $ret;
    }

    /**
     * 二维数组转哈希映射 (键值对)
     * @param array $arr 数据源
     * @param string $keyField 作为键的字段
     * @param string|null $valueField 作为值的字段,null 则整行作值
     * @return array 键值映射数组
     */
    public static function toHashmap(array $arr, string $keyField, string $valueField = null): array {
        $ret = [];
        if ($valueField) {
            foreach ($arr as $row) $ret[$row[$keyField]] = $row[$valueField];
        } else {
            foreach ($arr as $row) $ret[$row[$keyField]] = $row;
        }
        return $ret;
    }

    /**
     * 二维数组按指定字段分组
     * @param array $arr 数据源
     * @param string $keyField 分组依据字段
     * @return array 分组后数组 [key => [rows...]]
     */
    public static function groupBy(array $arr, string $keyField): array {
        $ret = [];
        foreach ($arr as $row) {
            $key = $row[$keyField];
            $ret[$key][] = $row;
        }
        return $ret;
    }

    /**
     * 扁平数组转树形结构 (引用赋值,O(N) 单遍历)
     * @param array $arr 数据源 (含 id, parent_id)
     * @param string $keyNodeId 节点ID字段
     * @param string $keyParentId 父ID字段
     * @param string $keyChildrens 子节点容器字段
     * @param array|null $refs 输出节点引用表 [id => &node]
     * @return array 树形数组
     */
    public static function toTree(array $arr, string $keyNodeId, string $keyParentId = 'parent_id', string $keyChildrens = 'childrens', array &$refs = null): array {
        $refs = [];
        // 1. 初始化子节点容器 + 建立引用表
        foreach ($arr as $offset => $row) {
            $arr[$offset][$keyChildrens] = [];
            $refs[$row[$keyNodeId]] = &$arr[$offset];
        }
        // 2. 组装树
        $tree = [];
        foreach ($arr as $offset => $row) {
            $parentId = $row[$keyParentId];
            if ($parentId) {
                if (!isset($refs[$parentId])) { // 孤儿节点当根
                    $tree[] = &$arr[$offset];
                    continue;
                }
                $refs[$parentId][$keyChildrens][] = &$arr[$offset];
            } else {
                $tree[] = &$arr[$offset];
            }
        }
        return $tree;
    }

    /**
     * 树形数组展开为扁平数组 (逆向操作)
     * @param array $tree 树形数组
     * @param string $keyChildrens 子节点字段
     * @return array 扁平数组
     */
    public static function treeToArray(array $tree, string $keyChildrens = 'childrens'): array {
        $ret = [];
        if (isset($tree[$keyChildrens]) && is_array($tree[$keyChildrens])) {
            foreach ($tree[$keyChildrens] as $child) {
                $ret = array_merge($ret, self::treeToArray($child, $keyChildrens));
            }
            unset($tree[$keyChildrens]);
        }
        $ret[] = $tree;
        return $ret;
    }

    /**
     * 单列排序 (升序/降序)
     * @param array $array 待排序数组
     * @param string $keyname 排序键
     * @param int $dir SORT_ASC/SORT_DESC
     * @return array 排序后数组
     */
    public static function sortByCol(array $array, string $keyname, int $dir = SORT_ASC): array {
        return self::sortByMultiCols($array, [$keyname => $dir]);
    }

    /**
     * 多列排序 (类比 SQL ORDER BY col1 ASC, col2 DESC)
     * @param array $rowset 待排序二维数组
     * @param array $args ['col1' => SORT_ASC, 'col2' => SORT_DESC]
     * @return array 排序后数组
     */
    public static function sortByMultiCols(array $rowset, array $args): array {
        $sortArrays = [];
        $sortRule = '';
        foreach ($args as $field => $dir) {
            foreach ($rowset as $offset => $row) {
                $sortArrays[$field][$offset] = $row[$field];
            }
            $sortRule .= '$sortArrays[\'' . $field . '\'], ' . $dir . ', ';
        }
        if (!$sortArrays) return $rowset;
        eval('array_multisort(' . $sortRule . '$rowset);'); // 动态构造调用
        return $rowset;
    }
}

核心方法使用示例

1. 清洗表单提交数组

$data = ['name' => '  John  ', 'email' => '', 'tags' => ['php', '  ', 'java']];
ArrayHelper::removeEmpty($data);
// 结果: ['name' => 'John', 'tags' => ['php', 'java']]

2. 提取 ID 列表用于 IN 查询

$orders = [
    ['id' => 1, 'amount' => 100],
    ['id' => 2, 'amount' => 200],
];
$ids = ArrayHelper::getCols($orders, 'id'); // [1, 2]
$sql = 'SELECT * FROM products WHERE id IN (' . implode(',', $ids) . ')';

3. 快速查找映射 (O(1) 替代 O(N) 遍历)

$users = [
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
];
$map = ArrayHelper::toHashmap($users, 'id', 'name'); // [1 => 'Alice', 2 => 'Bob']
echo $map[1]; // 直接命中,无需循环

4. 分组统计 (如按状态分组订单)

$orders = [
    ['id' => 1, 'status' => 'paid'],
    ['id' => 2, 'status' => 'pending'],
    ['id' => 3, 'status' => 'paid'],
];
$grouped = ArrayHelper::groupBy($orders, 'status');
// ['paid' => [[id=>1], [id=>3]], 'pending' => [[id=>2]]]

5. 无限级分类树构建 (单次遍历 O(N))

$categories = [
    ['id' => 1, 'parent_id' => 0, 'name' => '电子产品'],
    ['id' => 2, 'parent_id' => 1, 'name' => '手机'],
    ['id' => 3, 'parent_id' => 2, 'name' => 'iPhone'],
    ['id' => 4, 'parent_id' => 0, 'name' => '图书'],
];
$tree = ArrayHelper::toTree($categories, 'id', 'parent_id', 'children', $refs);
// 结果: 电子产品 -> 手机 -> iPhone; 图书
// 任意节点子树: $refs[2] 即手机及其所有子分类

6. 多字段排序 (先按 parent 升序,再按 name 降序)

$items = [
    ['parent' => 2, 'name' => 'B'],
    ['parent' => 1, 'name' => 'A'],
    ['parent' => 1, 'name' => 'C'],
];
$sorted = ArrayHelper::sortByMultiCols($items, [
    'parent' => SORT_ASC,
    'name' => SORT_DESC,
]);
// 结果: parent=1 (C, A), parent=2 (B)

性能与设计亮点

  • 引用赋值 (&):树构建无复制,内存极省,修改 $refs 即修改原数组
  • 单遍历 O(N):toTree 两次线性遍历,无递归,万级数据毫秒级
  • eval 动态 multisort:变参数排序优雅实现,注意参数已转义安全
  • 纯静态无状态:线程安全,直接 ArrayHelper::method() 调用

扩展建议

  1. 添加 keyExists()、pluck() (别名 getCols)、flatten() (别名 treeToArray)
  2. 引入严格类型 declare(strict_types=1) + 返回类型声明
  3. 单元测试覆盖边界情况:空数组、缺键、循环引用、深度嵌套
  4. 发布为 Composer 包 vendor/array-helper,按 PSR-4 自动加载
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved