如何按指定列顺序遍历含数组的Table、Row、Cell类实例
嘿,我来帮你捋捋这个问题——其实核心就是让Row能拿到Table的列顺序,然后按照这个顺序来遍历Cell就行,不管是用IteratorAggregate还是Iterator接口都能解决,我给你具体说说怎么实现:
思路核心
Table持有列顺序,而Row需要按照这个顺序返回Cell,所以关键是让Row类能获取到Table的列顺序信息。你不需要强行替换IteratorAggregate,它本身就很适合这种场景——我们只需要调整Row返回的迭代器逻辑就行。
方案一:基于IteratorAggregate的实现(推荐)
这种方式把迭代逻辑和Row的核心业务逻辑分离,代码更清晰:
- 调整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); } }
- 调整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); } }
- 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
相关产品推荐
相关产品推荐

