在PHP中快速比较两个数组

在PHP中快速比较两个数组,php,arrays,csv,sorting,multidimensional-array,Php,Arrays,Csv,Sorting,Multidimensional Array,所以我读了2个csv文件,大约有25k条记录。一个是旧CSV,一个是新CSV。我需要比较新CSV文件中的“主要联系人”字段是否与旧CSV记录不同,而旧CSV和新CSV中的“姓名”、“州”和“城市”字段是否相同 新CSV: Array( [0] => Array ( [0] => ID [1] => NAME [2] => STATE [3] => CITY [4] =>

所以我读了2个csv文件,大约有25k条记录。一个是旧CSV,一个是新CSV。我需要比较新CSV文件中的“主要联系人”字段是否与旧CSV记录不同,而旧CSV和新CSV中的“姓名”、“州”和“城市”字段是否相同

新CSV:

Array(

[0] => Array
    (
        [0] => ID
        [1] => NAME
        [2] => STATE
        [3] => CITY
        [4] => COUNTY
        [5] => ADDRESS
        [6] => PHONE
        [7] => PRIMARY CONTACT
        [8] => POSITION
        [9] => EMAIL
    )

[1] => Array
    (
        [0] => 2002
        [1] => Abbeville Christian Academy
        [2] => Alabama
        [3] => Abbeville
        [4] => Henry
        [5] => Po Box 9 Abbeville, AL 36310-0009
        [6] => (334) 585-5100
        [7] => Ashley Carlisle
        [8] => Athletic Director
        [9] => acarlisle@acagenerals.org
    )

}
问题是,我做了两个foreach嵌套循环来比较,这对于smal记录来说很好,但是当我运行每个都包含25k条记录的新旧CSV文件时,这个过程需要花费很长时间才能完成

在两个CSV中都有一些重复项,所以我先删除它们

function multi_unique($data){
    $data = array_reverse($data);

    $result = array_reverse( // Reverse array to the initial order.
        array_values( // Get rid of string keys (make array indexed again).
            array_combine( // Create array taking keys from column and values from the base array.
                array_column($data, 1), 
                $data
            )
        )
    );

    return $result;
}

$old_csv=multi_unique($old_csv);
$new_csv=multi_unique($new_csv);
这是我的比较代码,我需要比这更快的东西

$name_index_no = 1;
$state_index_no = 2;
$city_index_no = 3;
$country_index_no = 4;
$address_index_no = 5;
$primary_contact_index_no = 7;
$new_export_records[] = $old_csv[0];

foreach($new_csv as $key=>$value){

    foreach($old_csv as $key1=>$value1){

        if( $old_csv[$key1][$state_index_no] == $new_csv[$key][$state_index_no] &&
            $old_csv[$key1][$city_index_no] == $new_csv[$key][$city_index_no] &&
            $old_csv[$key1][$name_index_no] == $new_csv[$key][$name_index_no] ){

            if($old_csv[$key1][$primary_contact_index_no] != 
               $new_csv[$key][$primary_contact_index_no]){

                $new_export_records[] = $new_csv[$key];

            }

            unset($old_csv[$key1]);
            break;
        }

    }

}

正如Michael指出的,您当前的解决方案运行了
n*m
次。每一个都是25k,这简直太多了。但是,如果您先运行旧数据,创建一个索引,然后运行新数据并对照该索引进行检查,您将在
m+n
迭代中完成

例如:

$name_index_no            = 1;
$state_index_no           = 2;
$city_index_no            = 3;
$country_index_no         = 4;
$address_index_no         = 5;
$primary_contact_index_no = 7;

$genKey = function ($row, $glue = '|') use ($state_index_no, $city_index_no, $name_index_no) {
    return implode($glue, [
        $row[$state_index_no],
        $row[$city_index_no],
        $row[$name_index_no],
    ]);
};


// create an index using the old data
$t = microtime(true);
$index = [];
foreach ($old_csv as $row) {
    $index[$genKey($row)] = $row;
}

printf('index generation: %.5fs', microtime(true) - $t);

// collect changed/new entries
$t = microtime(true);
$changed = [];
$new = [];
foreach ($new_csv as $row) {
    $key = $genKey($row);

    // key doesn't exist => new entry
    if (!isset($index[$key])) {
        $new[] = $row;
    }

    // primary contact differs => changed entry
    elseif ($row[$primary_contact_index_no] !== $index[$key][$primary_contact_index_no]) {
        $changed[] = $row;
    }
}

printf('comparison: %.5fs', microtime(true) - $t);
print_r($changed);
print_r($new);

正如Michael指出的,您当前的解决方案运行了
n*m
次。每一个都是25k,这简直太多了。但是,如果您先运行旧数据,创建一个索引,然后运行新数据并对照该索引进行检查,您将在
m+n
迭代中完成

例如:

$name_index_no            = 1;
$state_index_no           = 2;
$city_index_no            = 3;
$country_index_no         = 4;
$address_index_no         = 5;
$primary_contact_index_no = 7;

$genKey = function ($row, $glue = '|') use ($state_index_no, $city_index_no, $name_index_no) {
    return implode($glue, [
        $row[$state_index_no],
        $row[$city_index_no],
        $row[$name_index_no],
    ]);
};


// create an index using the old data
$t = microtime(true);
$index = [];
foreach ($old_csv as $row) {
    $index[$genKey($row)] = $row;
}

printf('index generation: %.5fs', microtime(true) - $t);

// collect changed/new entries
$t = microtime(true);
$changed = [];
$new = [];
foreach ($new_csv as $row) {
    $key = $genKey($row);

    // key doesn't exist => new entry
    if (!isset($index[$key])) {
        $new[] = $row;
    }

    // primary contact differs => changed entry
    elseif ($row[$primary_contact_index_no] !== $index[$key][$primary_contact_index_no]) {
        $changed[] = $row;
    }
}

printf('comparison: %.5fs', microtime(true) - $t);
print_r($changed);
print_r($new);


你认为什么是你需要的合理表现?你需要在瞬间得到答案吗?几秒钟?在当前的解决方案中,您的运行时复杂性为O(n^2),这不是很好:)您只是想知道这两个文件是否至少在其中一个字段中存在差异,还是想收集所有相关行(例如,在下一步中使用它)?@Michael,如果可以在一瞬间完成,那将非常棒。你有什么建议吗?@Yoshi,如果我说只有一个值不同,那么我如何快速比较并获得与该特定值不同的新CSV记录(“主要联系人”请参见上面的数组)?@再次。。这取决于你的需要,你需要像数据库一样思考这个问题,你有两个优势1。快速查询时间2。快速索引(或读取)时间。那么您需要读取文件并实时向用户显示输出吗?或者这是一个2个独立的过程?你认为什么是你的需要的合理表现?你需要在瞬间得到答案吗?几秒钟?在当前的解决方案中,您的运行时复杂性为O(n^2),这不是很好:)您只是想知道这两个文件是否至少在其中一个字段中存在差异,还是想收集所有相关行(例如,在下一步中使用它)?@Michael,如果可以在一瞬间完成,那将非常棒。你有什么建议吗?@Yoshi,如果我说只有一个值不同,那么我如何快速比较并获得与该特定值不同的新CSV记录(“主要联系人”请参见上面的数组)?@再次。。这取决于你的需要,你需要像数据库一样思考这个问题,你有两个优势1。快速查询时间2。快速索引(或读取)时间。那么您需要读取文件并实时向用户显示输出吗?或者这是一个2个独立的进程?我尝试了你的代码,但它只提供了9条记录$changed数组,但有2k+条记录是不同的,这是我从嵌套循环中获得的,在我的core i7机器上运行大约3分钟,在我的VPS主机上运行大约6分钟。检查的字段是否可能存在重复项(州、市、名)?我之前也删除了重复项,请参见我的更新后的上述回答。我将代码更改为使用字符串键(所需字段的串联),请尝试使用更新后的代码。我想我发现了问题,基本上我的互联网上传速度很慢(我正在上传CSV),因为我刚刚对第一行代码计时并在第一行之后退出,但这需要一些时间。但时间结果很快。我尝试了你的代码,但它只提供了9条记录$changed array,但有2k+条记录是不同的,这是我从嵌套循环中获得的,在我的core i7机器上运行大约3分钟,大约需要6分钟在我的VPS主机上,检查的字段(州、城市、名称)是否可能存在重复项?我之前删除了重复项,请参阅我的更新的上述回答我更改了代码以使用字符串键(所需字段的串联),请尝试使用更新的代码。我想我发现了问题,基本上我的互联网上传速度很慢(我正在上传CSV),因为我只是对第一行代码计时,然后在第一行之后退出,但这需要一些时间。但时间结果很快。