这实际上与我之前问过的一个问题有关,其中有人好心地提供了一些我可以用来解决我提出的问题的代码。
现在,我理解了发布的大部分代码,直到我了解了 array_filter 用于检索重复行的位置。
作为参考,这是我之前提出的问题; PHP:以 OOP 方式搜索 CSV 文件
这是我很难完全理解正在发生的事情的地方;
public static function getRowsWithDuplicates($columnIndex) {
$values = array();
for ($i = 0; $i < $this->_dataSet->getRowCount(); ++$i) {
$values[$this->_dataSet->->getValueAt($i, $columnIndex)][] = $i;
}
return array_filter($values, function($row) { return count($row) > 1; });
}
首先;看看该代码,在我看来 $values 是一个关联数组。如果是这样,那么 array_filter 如何返回具有重复值的行?
我认为我没有完全理解 array_filter 发生的过程来理解这段代码;我知道 array_filter 将数组中的每个值传递到其参数中提供的函数中,然后从该函数返回一个值,但在这个特定的示例中,我认为我不明白 array_filter 内部到底发生了什么。
如果有人能在我可以逐步理解该过程的水平上向我解释,我将不胜感激,这样我就可以更好地理解上面代码中发生的事情,这样我就可以不仅仅是复制结果。
如果 $values 是关联数组,那么代码如何利用关联数组的属性来返回重复行?
我想这并不是我难以理解的函数本身,而是它在这种特殊情况下的使用方式。
return count($row) > 1;
我不明白比较运算符在返回值时的行为如何;是不是说只有当行数超过 1 行时才返回 TRUE,然后 array_filter 正在评估该 TRUE 语句并返回与其关联的值?
函数($row) 中的 $row 传递了什么?
如你所见,我的问题比答案多得多,我宁愿向我解释它,也不愿花太长时间猜测并得出错误的结论。
$row只是array_filter用来传入其迭代的数组值的参数吗?
编辑:这是我修改后的问题,更加具体,并且符合我正在寻找答案的问题;
我明白 array_filter 在做什么,但我不明白它是如何做到的。该代码的原始发布者 Jon 写道: “此代码将返回一个数组,其中键是 CSV 数据中的值,值是带有每个值出现的行的从零开始的索引的数组。”
这是我不明白的; $values 的值是数组,每个值出现的行的索引从零开始。代码如何找到每个值出现的每一行的索引,并将其放入 $values 中存储的数组中?
所以我的问题与这部分代码有关:
for ($i = 0; $i < $this->_dataSet->getRowCount(); ++$i) {
$values[$this->_dataSet->->getValueAt($i, $columnIndex)][] = $i;
代码如何找到匹配值的所有索引,将它们放入数组中,其中该数组的键是索引相关的值?
就像对重复值的整体搜索正在进行,但我看不到。
array_filter
中的回调应返回true
或false
。如果它返回 true
,则意味着应保留当前值。如果它返回 false
,则应丢弃当前值。
数组的每个值都作为其第一个参数传递给回调函数(在本例中为
$row
),然后由回调决定是否保留该值。
请允许我通过删除所有电子表格方法并声明要访问的简单二维数组来提供更简单的演示。
输入:(演示)
$lookup = [
['a', 'ape'],
['b', 'bee'],
['a', 'ant'],
['d', 'dog'],
['b', 'bat'],
['a', 'asp'],
];
function getValueAt($lookup, $rowIndex, $columnIndex) {
return $lookup[$rowIndex][$columnIndex];
}
$columnIndex = 0;
for
循环假设您打算迭代的输入数据已建立索引(无间隙结构,可以安全使用从 0 开始的数字键控)。
$values
是新声明的数组,将在其中收集新数据。
[getValueAt($lookup, $i, $columnIndex)]
部分指示新数组的第一级键将由函数的返回值确定。该技术将用于识别和分组相关数据。
后面的
[]
是语法糖,它将数据“推送”为所访问元素的子元素——因此,如果在新元素被推送到子数组的第一个位置之前没有遇到 $values[getValueAt($lookup, $i, $columnIndex)]
: $values[getValueAt($lookup, $i, $columnIndex)][0]
。下次收到来自 getValueAt()
的相同返回值时,生成的密钥将是子数组中的 [1]
。
在
$i
循环签名中声明的 for()
用作推入结果数组的值。这意味着分组的子数组不会丢失数据最初来自的位置。
处理代码:
$values = [];
for ($i = 0; $i < count($lookup); ++$i) {
$values[getValueAt($lookup, $i, $columnIndex)][] = $i;
}
所以
var_export($values);
将输出:
array (
'a' =>
array (
0 => 0, // ape
1 => 2, // ant
2 => 5, // asp
),
'b' =>
array (
0 => 1, // bee
1 => 4, // bat
),
'd' =>
array (
0 => 3, // dog
),
)
并且
var_export(array_filter($values, fn($row) => count($row) > 1));
将输出:
array (
'a' =>
array (
0 => 0, // ape
1 => 2, // ant
2 => 5, // asp
),
'b' =>
array (
0 => 1, // bee
1 => 4, // bat
),
)