【问题标题】:Compare 2 csv files and highlight row on match比较 2 个 csv 文件并在匹配时突出显示行
【发布时间】:2020-04-13 13:29:45
【问题描述】:

我有以下工作代码来比较 2 个 csv 文件 - base.csv 文件使用函数 row_compare 与 master.csv 文件进行比较。现在我正在回显 master.csv 文件,然后回显匹配项。我需要帮助以表格格式仅回显 master.csv 文件并突出显示与 base.csv 文件项匹配的行。

function row_compare($a, $b)
{
    if ($a === $b) {
        return 0;
    }

    return (implode("",$a) < implode("",$b) ) ? -1 : 1;
}

$file1 = new SplFileObject("master.csv");
$file1->setFlags(SplFileObject::READ_CSV);

$file2 = new SplFileObject("../../base.csv");
$file2->setFlags(SplFileObject::READ_CSV);

foreach ($file1 as $row) {
    $csv_1[] = $row;
}

foreach ($file2 as $row) {
    $csv_2[] = $row;
}

$unique_to_csv1 = array_udiff($csv_1, $csv_2, 'row_compare');
$unique_to_csv2 = array_udiff($csv_2, $csv_1, 'row_compare');

$all_unique_rows = array_merge($unique_to_csv1,$unique_to_csv2);

foreach($all_unique_rows as $unique_row) {
    foreach($unique_row as $element) {
        echo $element . "   ";
    }
    echo '<br />';
}

master.csv

02Jan2020,Marilyn Salary,-31570.29,162252.14,,
02Jan2020,Nancy Skosana,-30000,132252.14,,
02Jan2020,Johan Consulting Fees,-30000,102252.14,,
02Jan2020,Carol Consulting Fees,-30000,72252.14,,
02Jan2020,Juanic Salary,-24239.22,48012.92,,
02Jan2020,Shirley Salary,-14382.67,33630.25,,
06Jan2020,Carol Consulting Fees,-10000,72252.14,,
06Jan2020,Juanic Salary,-4239.22,48012.92,,
06Jan2020,Shirley Salary,-4382.67,33630.25,,

Base.csv

ADE Labeling
Johan Consulting Fees
Best Board
Nancy Skosana
Cabstrut
Juanic Salary
Cybertrek
Drizit
Shirley Salary

输出格式

因此,所有包含 Johan Consulting Fees、Shirley Salary、Juanic Salary 和 Nancy Skosan 的行都应变为黄色

【问题讨论】:

  • 您能否根据以上来自 master.csv 和 base.csv 的示例值显示您的预期输出?

标签: php csv match unique


【解决方案1】:
<?php
$file1 = new SplFileObject("master.csv");
$file1->setFlags(SplFileObject::READ_CSV);

$file2 = new SplFileObject("base.csv");
$file2->setFlags(SplFileObject::READ_CSV);

foreach ($file1 as $row) {
    $csv_1[] = $row;
}

//If there are just one column, just make a single level array
foreach ($file2 as $row) {
    $csv_2[] = $row[0];
}

//Create html-table with values from master csv file (master csv array $csv_1)
//and if name is the same in other array , make <tr class="yellow"> which
//would highlight the row
$html = '<table>';
foreach($csv_1 as $inner_arr) {
    $name = $inner_arr[1];    
    $arr_in = in_array($name, $csv_2); 

    $html .= '<tr';
    //Name exists in the other array, hightlight this row
    if ($arr_in !== false) {
        $html .= ' class="yellow"';
    }
    $html .= '>';

    foreach($inner_arr as $inner_value) {   
        $html .= '<td>';       
        $html .= $inner_value;    
        $html .= '</td>';
    }
    $html .= '</tr>';

}
$html .= '</table>';
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Table</title>
    <style type="text/css">
    .yellow {background:yellow;}
    </style>
</head>
<body>
  <?php echo $html;?>  
</body>
</html>

更新(应 OP 的要求): 如果您有多个“基础”文件,您可以这样做: 用这个替换第一部分代码:

<?php
$file1 = new SplFileObject("master.csv");
$file1->setFlags(SplFileObject::READ_CSV);

$basefiles = array('base.csv', 'base2.csv', 'base3.csv');
$file2 = array();
foreach($basefiles as $key=>$bf) {
    $file2[$key] = new SplFileObject( $bf );
    $file2[$key]->setFlags(SplFileObject::READ_CSV);
}

foreach ($file1 as $row) {
    $csv_1[] = $row;
}

$csv_2 = array();
//Go through all fileobjects and create arr ($csv_2) based on those files
foreach ($file2 as $file_object) {        
    //If there are just one column
    foreach($file_object as $row) {
        $csv_2[] = $row[0];
    }
}

//And then continue with creation with html-string as above
//(where line comment starts with:
//Create html-table with values from master csv file)

更新 2: 更好的方法是(来自@Nigels 建议)将文件对象的创建跳过到单独的数组中,并在为每个文件创建文件对象的第一个循环中创建文件数组。

<?php
$file1 = new SplFileObject("master.csv");
$file1->setFlags(SplFileObject::READ_CSV);

foreach ($file1 as $row) {
    $csv_1[] = $row;
}

$basefiles = array('base.csv', 'base2.csv', 'base3.csv');
$csv_2 = array();
foreach($basefiles as $key=>$bf) {
    $file2 = new SplFileObject( $bf );
    $file2->setFlags(SplFileObject::READ_CSV);
    foreach($file2 as $row) {
        $csv_2[] = $row[0];
    }
}

【讨论】:

  • 我还不能完整地回答你,但我会创建一个文件数组(而不是使用 $file2)并再次检查该数组。我会尽快回复您。
  • 现在按您的要求更新。
  • 读取数据而不是创建文件列表并遍历此列表以读取数据是否更有意义。
  • @JohanVenables - 嗯,你昨天没有接受 Nigels 的回答吗?
  • 至于接受答案,只要他们解决了他们的问题,这并不重要。
【解决方案2】:

如果主文件中的名称(第二列)在数据文件中(代码中的 cmets),则此代码将仅输出 *...

$file2 = new SplFileObject("../../base.csv");
$file2->setFlags(SplFileObject::READ_CSV);

// Read in second file, just create an entry indexed by the name
foreach ($file2 as $row) {
    $csv_2[$row[0]] = 1;
}

$file1 = new SplFileObject("master.csv");
$file1->setFlags(SplFileObject::READ_CSV);

echo "<table>";
// Loop through the master file
foreach($file1 as $row) {
    if ( isset($csv_2[$row[1]]) ) {
        $class = "yellow";
    }
    else    {
        $class = "green";
    }
    echo '<tr class="'.$class.'"><td>';
    echo implode("</td><td>", $row);
    echo '</td></tr>';
}
echo "</table>";

对于读取多个数据文件,这会将读取移动到一个函数...

function readDataFiles ( array $fileNames )  {
    $csv = [];

    foreach ( $fileNames as $fileName )    {
        $file2 = new SplFileObject($fileName);
        $file2->setFlags(SplFileObject::READ_CSV);

        foreach ($file2 as $row) {
            $csv[$row[0]] = 1;
        }
    }

    return $csv;
}
$csv_2 = readDataFiles(["base1.csv", "base2.csv"]);

【讨论】:

  • 啊。聪明的把名字设置为key。这种方法有什么缺点吗?
  • @bestprogrammerintheworld,如果你只需要知道一个条目存在,那么据我所知。
  • 如果我有 10 个基本文件(base1.csv、base2.csv、base3.csv ... 等),还有一件事我如何遍历它们以检查 master.csv 文件
  • 如果它们是相同或相似的比较,将它们全部读入同一个数组会更容易,因此对每个文件重复 foreach ($file2 as $row) {... 循环(或创建一个函数来执行给你)。
  • 我试图读取同一个数组中的多个 csv 文件,但只给了我最后一个 csv 文件匹配的结果$file2 = new SplFileObject("../../base.csv"); $file2-&gt;setFlags(SplFileObject::READ_CSV); $file2 = new SplFileObject("../../base1.csv"); $file2-&gt;setFlags(SplFileObject::READ_CSV);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多