Check for duplicates in all lists before moving item to list

I have a master list populated from a master.csv file then I have multiple (10+) list populated from list1.csv, list2.csv, list3.csv …etc. I want to move items from masterlist to list1 but need to check that item is not in any of the lists before it can be moved Herewith code but only use 3 list but there is more but I am unable to check for duplicates before move

index.php

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Move Items From Master List</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
    </script>

</head>

<select name=master[] id=master class="master" multiple="multiple" size='23'>
<?php   
    $file = fopen("temp.csv", "r");
    while (($row = fgetcsv($file, 0, ",")) !== FALSE) {
        $master = $row[0];
?>
    <option><?php echo $master; ?></option>
<?php
    }
?>
</select> 

<form action="update.php" method="post">
    <input type=button class="master" name=b1 id=b1 value='Move >'>
    <input type=button class="master" name=b2 id=b2 value='< Remove'>&nbsp;&nbsp;&nbsp;&nbsp;
<select name=list1[] id=list1 multiple="multiple" class=master>
<?php   
    $file = fopen("list1.csv", "r");
    while (($row = fgetcsv($file, 0, ",")) !== FALSE) {
        $list1 = $row[0];
?>
    <option value="<?php echo $list1;?>"><?php echo $list1;?></option>
<?php
    }
?>
</select>
&nbsp;&nbsp;&nbsp;&nbsp;<input type="submit" value="Save File" name="submit">
</form><br /><br />

<form action="update.php" method="post">
    <input type=button class="master" name=b3 id=b3 value='Move >'>
    <input type=button class="master" name=b4 id=b4 value='< Remove'>&nbsp;&nbsp;&nbsp;&nbsp;
<select name=list2[] id=list2 multiple="multiple" class=master>
<?php   
    $file = fopen("list2.csv", "r");
    while (($row = fgetcsv($file, 0, ",")) !== FALSE) {
        $list2 = $row[0];
?>
    <option value="<?php echo $list2;?>"><?php echo $list2;?></option>
<?php
    }
?>
</select>
&nbsp;&nbsp;&nbsp;&nbsp;<input type="submit" value="Save File" name="submit">
</form>

 <script>
 $("#b1").click(function() {
    var source = $("#master");
    var target = $("#list1");
    $("option:selected", source).each(function() {
        target.append("<option>" + $(this).text() + "</option>");
        $("option[value= '" + $(this).val() + "' ]", source).remove();
    });
    $('option', target).prop('selected', true);
});

$("#b2").click(function(){
    var source = $("#list1");
    var target = "#master";
    $("option:selected", source).each(function() {
        master.append("<option>"+$(this).text()+"</option>");
        $("option[value= '"+ $(this).val() + "' ]", source).remove();
    });
    $('option', source).prop('selected', true);
});

$("#b3").click(function() {
    var source = $("#master");
    var target = $("#list2");
    $("option:selected", source).each(function() {
        target.append("<option>" + $(this).text() + "</option>");
        $("option[value= '" + $(this).val() + "' ]", source).remove();
    });
    $('option', target).prop('selected', true);
});

$("#b4").click(function(){
    var source = $("#list2");
    var target = "#master";
    $("option:selected", source).each(function() {
        master.append("<option>"+$(this).text()+"</option>");
        $("option[value= '"+ $(this).val() + "' ]", source).remove();
    });
    $('option', source).prop('selected', true);
});
    </script>

and my update.php file

<?php
header("Location:".$URL.'index.php');

if ($_POST['list1']) {
$list1 = $_POST['list1'];
$list1unique = array_unique($list1);
sort($list1unique);
foreach ($list1unique as $key => $value) {
    $result.=$value."\n";
}
file_put_contents('list1.csv',$result);
}

if ($_POST['list2']) {
$list2 = $_POST['list2'];
$list2unique = array_unique($list2);
sort($list2unique);
foreach ($list2unique as $key => $value) {
    $result.=$value."\n";
}
file_put_contents('list2.csv',$result);
}

?>

Check out the following list of PHP Array functions because all array items must be unique.

Please supply sample values in the CSV file so I can check to see if the following script works:

foreach($masterlist as $key => $item):
 if( array_key_exists($masterlist, $item)  ): 
    // do nothing
 else:
    array_push($list1, $item);
    // perhaps delete from $master[$key]
    // $master[$key] = NULL; 
 endif;
endforeach ;

master.csv

January
February
March
April
May
June
July
August
September
October
November
December

list1.csv

January
February

list2.csv

March
April

Try this:

<?php DECLARE(STRICT_TYPES=1);  
error_reporting(-1);
ini_set('display_errors', 'On');

$master = csvToArray('master.csv');
$list1  = csvToArray('list1.csv');
$list2  = csvToArray('list2.csv');

echo '<h1> BEFORE CSV </h1>';
  fred($master, '$master');
  fred($list1,  '$list1');
  fred($list2,  '$list2');
echo '<hr>';

echo '<h1> AFTER CSV and Pushing to $list1[] </h1>';
  checkAndRemove($master, $list1);
  fred($master, '$master');
  fred($list1,  '$list1');

echo '<h1> AFTER CSV and Pushing to $list2[] </h1>';
  checkAndRemove($master, $list2);
  fred($master, '$master');
  fred($list2,  '$list2');



//=============================================
  
  // Only functions below 

//=============================================  



//===========================================================
function fred($val, $title='')
{
  echo '<hr><pre>' 
      . '<b>' .$title .'</b> ==> '
      .print_r($val, true) .'</pre><hr>'; 
} 

//===============================================
function csvToArray
(
  string $csvFile 
) : array // $result  
{
  $result = [];

  $file = fopen($csvFile, "r");

  $csvFile = fopen($csvFile, "r");
  while (($row = fgetcsv($csvFile, 0, ",")) !== FALSE)
  {
    $result[] = $row[0];
  }        

  return $result;
}

//=======================================
function checkAndRemove( & $master, & $test)
{
  foreach($master as $key => $item):
   if( in_array($item, $test)  ): 
      // do nothing
   else:
      array_push($test, $item);
      // perhaps delete from $master[$key]
      $master[$key] = NULL; 
   endif;
  endforeach ;

  return ; // $master;
}

Tried your code as is but receive error

Fatal error : Uncaught Error: Call to undefined function csvToArray() in …/index.php:5 Stack trace: #0 {main} thrown in …/index.php on line 5

I did change my temp.csv to master.csv

Your statement of what you are trying to do, combined with the example data, lacks clarity. I also reviewed your most recent posts and do these csv files actually contain lines of csv data or are they really just single values on each line in the file?

I’m reading this as - since January, February, March, and April are already picked and stored in the output files, they are unavailable to be picked when this page is displayed, any of the remaining available choices can be added to any output file, and any choice made while on this ‘edit’ page should ‘dynamically’ become unavailable in all the select/option menus?

Next, don’t write out block after block of the same program logic that only differs in the data values it operates on. Let the computer generate the html markup and process the submitted data for the 10 possible files by looping to produce the html markup and looping to dynamically process the 10 sets of data from the form.

They contain single values on each line

What I need to do is if January is in list1 and I try to move January from master list to list 2 it shouldn’t because it is already allocated to list1

I can’t remove it from masterlist as I use master list for other application and calculation

block of the same program logic - Understand will be doing that

Then you don’t need all the extra code treating it as csv data. Just use file(), with the FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES flags, to get all the lines from any file into an array.

You would read the contents of all the files, then if a choice exists in one of the 10+ output files, either leave the choice(s) out of the master select/option list or you would add the disabled attribute.

How do you know how many output files there are? Do you have some type of ‘add’ menu choice to add an empty one?

No one stated to do anything to the master.csv file. Once you read the contents of the file into memory, you can do anything you want to that copy of the data.

Because you have used a separate form for each output file, I’ll assume that you want to update one output file at a time, then go onto the next? This makes the overall logic simpler since you won’t need to ‘dynamically’ remove choices using javascript in the browser as you make sections and restore those choices if you remove a selection.

Thanx for pointing out how to get all lines into an array

Output files will be fixed once finalized at this stage there is 21 but can be more

Yes I update one output file at a time

The logic to read the existing data needs to be all together and before the start of the html document -

// get method business logic - get/produce data needed to display the page

$num_files = 10; // if this is dependent on some 'dynamic' value, change the logic for this value get the actual number of files to handle

// read existing data

$master = file('master.csv',FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );

$list = []; // individual file contents
$all = []; // all existing selections merged into one array
foreach(range(1,$num_files) as $num)
{
	$file = "list{$num}.csv"; // form the file name
	$list[$num] = []; // initialize to an empty array
	if(file_exists($file))
	{
		$list[$num] = file($file,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
		$all = array_merge($all,$list[$num]);
	}
}

At the point of producing the master select/option menu, this is all the logic you need -

<select name=master[] id=master class="master" multiple="multiple" size='23'>
<?php
foreach($master as $value)
{
	if(!in_array($value,$all))
	{
		echo "<option>$value</option>\n";
	}
}
?>
</select>

The $list variable is an array of arrays, with the main index being the output file number 1…10 or whatever the maximum is. You would loop over this array to get the file number and the array of existing values that were read from that corresponding file, to produce the select/option menus in the rest of the code.

Thanx works 100% just want to test something when uploading item to master list what influence it will have will get back to you if any problems Just need to quickly run to store for groceries

<form method="POST" action="update.php">
     Name <input type="text" name="masterlistitem" value="" />
<br /><br />
<input  type="submit"  value=" Update " /> 
</form>

will update my update.php file when I get back

OK have done my testing uploading item and everything is working 100% Just want to thank you I was spending 2 days looking at various ways to accomplish.

How can i make one function for following logic

if ($_POST['list1']) {
$list1 = $_POST['list1'];
$list1unique = array_unique($list1);
sort($list1unique);
foreach ($list1unique as $key => $value) {
    $result.=$value."\n";
}
file_put_contents('list1.csv',$result);
}

if ($_POST['list2']) {
$list2 = $_POST['list2'];
$list2unique = array_unique($list2);
sort($list2unique);
foreach ($list2unique as $key => $value) {
    $result.=$value."\n";
}
file_put_contents('list2.csv',$result);
}

if ($_POST['list3']) {
$list3 = $_POST['list3'];
$list3unique = array_unique($list3);
sort($list3unique);
foreach ($list3unique as $key => $value) {
    $result.=$value."\n";
}
file_put_contents('list3.csv',$result);
}

… etc

Start by defining -

  1. What data you (should) have as an input.
  2. What processing you are going to do based on all possible values of those inputs.
  3. What result or output are you going to produce.

What I came up with for those -

  1. A list number/id (integer.) An array of choices (strings). Note: If the master choices were defined/stored in a database table, the submitted choices would be integer ids instead of strings.
  2. There must be a non-empty list number/id with a value between one and the maximum permitted/defined value.
    To allow for ‘clearing’ a list, the array of choices may not exist (a select/option menu that has nothing selected isn’t a successful form field and isn’t included in the form data.)
    If there is an array of choices, remove empty values (a value that’s set but is an empty string/zero), remove duplicates, and sort the remaining values.
  3. Save the choices to a file - list{id}.csv, one line per choice. If clearing the list, save an empty file.

Note: To allow for clearing a list, the list number/id must be a separate form field from the select/option menu, since the select/option field won’t be submitted in this case. A hidden field should be used for the list number/id. This would require adding a hidden field to your existing form(s) for the list number/id, then remove the list number/id from the end of the select field name attribute.