You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按指定列顺序遍历含数组的Table、Row、Cell类实例

嘿,我来帮你捋捋这个问题——其实核心就是让Row能拿到Table的列顺序,然后按照这个顺序来遍历Cell就行,不管是用IteratorAggregate还是Iterator接口都能解决,我给你具体说说怎么实现:

思路核心

Table持有列顺序,而Row需要按照这个顺序返回Cell,所以关键是让Row类能获取到Table的列顺序信息。你不需要强行替换IteratorAggregate,它本身就很适合这种场景——我们只需要调整Row返回的迭代器逻辑就行。

方案一:基于IteratorAggregate的实现(推荐)

这种方式把迭代逻辑和Row的核心业务逻辑分离,代码更清晰:

  1. 调整Table类:在添加Row的时候,把自身的列顺序传递给Row
class Table implements IteratorAggregate {
    private array $rows = [];
    private array $columnOrder;

    public function __construct(array $columnOrder) {
        $this->columnOrder = $columnOrder;
    }

    public function addRow(Row $row): void {
        // 将Table的列顺序传递给当前Row
        $row->setColumnOrder($this->columnOrder);
        $this->rows[] = $row;
    }

    public function getIterator(): Traversable {
        return new ArrayIterator($this->rows);
    }
}
  1. 调整Row类:存储Cell时用列名作为键,然后在getIterator()里按照列顺序生成迭代器
class Row implements IteratorAggregate {
    private array $cells = [];
    private array $columnOrder = [];

    // 用列名作为Cell的键,方便后续按列顺序查找
    public function addCell(string $columnName, Cell $cell): void {
        $this->cells[$columnName] = $cell;
    }

    public function setColumnOrder(array $columnOrder): void {
        $this->columnOrder = $columnOrder;
    }

    public function getIterator(): Traversable {
        $orderedCells = [];
        // 按照Table指定的列顺序依次取出对应的Cell
        foreach ($this->columnOrder as $columnName) {
            // 可以根据需求处理列不存在的情况:比如跳过或添加空Cell
            if (isset($this->cells[$columnName])) {
                $orderedCells[] = $this->cells[$columnName];
            }
        }
        return new ArrayIterator($orderedCells);
    }
}
  1. Cell类保持不变
class Cell {
    public function __construct(public string $textValue) {}
}

方案二:改用Iterator接口实现

如果你确实想换成Iterator接口,也可以让Row直接实现Iterator,维护迭代的位置和列顺序:

class Row implements Iterator {
    private array $cells = [];
    private array $columnOrder = [];
    private int $position = 0;

    public function addCell(string $columnName, Cell $cell): void {
        $this->cells[$columnName] = $cell;
    }

    public function setColumnOrder(array $columnOrder): void {
        $this->columnOrder = $columnOrder;
        $this->position = 0; // 重置迭代位置
    }

    public function current(): mixed {
        $currentColumn = $this->columnOrder[$this->position];
        return $this->cells[$currentColumn] ?? null;
    }

    public function next(): void {
        $this->position++;
    }

    public function key(): mixed {
        return $this->position;
    }

    public function valid(): bool {
        // 检查当前位置的列是否存在,且对应的Cell存在
        return isset($this->columnOrder[$this->position]) 
            && isset($this->cells[$this->columnOrder[$this->position]]);
    }

    public function rewind(): void {
        $this->position = 0;
    }
}

效果验证

当你遍历Table的Row时,每个Row的迭代器都会按照Table初始化时指定的列顺序返回Cell,而不是Cell的添加顺序。比如:

// 创建一个指定列顺序的Table
$table = new Table(['name', 'age', 'email']);

// 创建Row并添加Cell(打乱顺序)
$row = new Row();
$row->addCell('age', new Cell('25'));
$row->addCell('name', new Cell('Alice'));
$row->addCell('email', new Cell('alice@example.com'));

$table->addRow($row);

// 遍历Table的Row,再遍历Row的Cell
foreach ($table as $row) {
    foreach ($row as $cell) {
        echo $cell->textValue . PHP_EOL;
    }
}
// 输出顺序:Alice → 25 → alice@example.com

内容的提问来源于stack exchange,提问作者Remo Fiorentino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:08:39