Сравните 2 CSV-файла и выделите строку в совпадении - PullRequest
1 голос
/ 13 апреля 2020

У меня есть следующий рабочий код для сравнения 2 CSV-файлов - файл base.csv для сравнения с файлом master.csv с помощью функции row_compare. Сейчас я повторяю файл 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

Выходной формат

enter image description here

Таким образом, все строки, содержащие сборы за консультацию Йохана, зарплата Ширли, зарплата Хуани c а Нэнси Скосан должна смениться на желтый

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020
<?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)

UPDATE2: Лучшим подходом (из рекомендации @Nigels) было бы пропустить создание файловых объектов в отдельном массиве и создать массив файлов в первом l oop где файловые объекты создаются для каждого файла.

<?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];
    }
}
1 голос
/ 13 апреля 2020

Этот код будет просто выводить *, если имя (второй столбец) в главном файле находится в файле данных (комментарии в коде) ...

$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"]);
...