PHP creating a unique Array with foldernames where no duplicates are mentioned - php

I want to create a unique array to show which folders got deleted. All files are stored in a .txt and can only be read.
function createUniqueArr(array $arr){
$uniqueArray = array();
foreach($arr as $i => $string){
foreach($uniqueArray as $j => $string){
if(!(str_contains($uniqueArray[$j], $arr[$i]))){
$uniqueArray[$j] = $arr[$i];
}
}
}
return $uniqueArray;
}
This is the code i have so far but it does not seem to work.
NOTE: The full Folder name is in the array before all subfiles.
The array that is given looks like this, every new line is a new index:
test/test/folder1
test/test/folder1/example.txt
test/test/folder1/example2.txt
test/test/folder1/example3.txt
test/test/folder1/example4.txt
test/test/folder1/example5.txt
test/thisFolderShoudBeShownFully/example6.txt
The disered array should be something like this:
> test/test/folder1
> test/thisFolderShoudBeShownFully/example6.txt
Hope someone can help me

I'd iterate over the list once to get an array of the directories, then again to exclude lines that have a directory in that list. This doesn't require the input to be sorted such that the directory lines are first.
$dirs = array_filter($list, fn($line) => !preg_match('/\.txt$/', $line));
$new = array_filter($list, fn($line) => !in_array(dirname($line), $dirs));
print_r($new);
Array
(
[0] => test/test/folder1
[6] => test/thisFolderShoudBeShownFully/example6.txt
)

Related

Multidimensional array keys to variable

sadly i havent found any solution yet.
I have an multidimensional array which looks like this:
Array
(
[0] => Array
(
[Symbol] => CASY.US
[Position] => 169873920
)
[1] => Array
(
[Symbol] => US500
[Position] => 168037428
) )
Now i want to write the name of the keys of the inner array into variables so that i have these variables with the values:
$col1 = "Symbol"
$col2 = "Position"
How can i achieve that? Somehow with a couple of foreach loops?
Background: After that i want to check if the columns have the right name for a validation.
Thanks in advance!
Loop nested and save the keys to an array with "col" and an integer that you later can (if you really must extract), but I recommend to keep them in the array.
foreach($array as $subarray){
$i = 1;
foreach($subarray as $key => $val){
$keys["col" . $i] = $key;
$i++;
}
break; // no need to keep looping if the array is uniform
}
//if you must:
extract($keys);
https://3v4l.org/ALVtp
If the subarrays are not the same then you need to loop all subarrays and see if the key has already been saved, if not save it else skip it.
$keys =[];
$i = 1;
foreach($array as $subarray){
foreach($subarray as $key => $val){
if(!in_array($key, $keys)){
$keys["col" . $i] = $key;
$i++;
}
}
}
var_dump($keys);
//if you must:
extract($keys);
var_dump($col1, $col2, $col3);
https://3v4l.org/EklPK
Honestly I would do something like this:
$required = array_flip(['Symbol', 'Position']); //flip because I am lazy like that ['Symbol'=>0, 'Position'=>1]
foreach($array as $subarray){
$diff = array_diff_key($required, $subarray);
//prints any keys in $required that are not in $subarray
print_r($diff);
if(!empty($diff)){
//some required keys were missed
}
}
While its not clear how you validate these the reason is as I explained in this comment
it still doesn't solve the problem, as you really have no way to know what the keys will be (if they are not uniform). So with my example foo is $col3 what if I have bar later that's $col4 what if the order is different next time.... they will be different numbers. Sure it's a few what if's but you have no guarantees here.
By dynamically numbering the keys, if the structure of the array ever changes you would have no idea what those dynamic variables contain, and as such no idea how to validate them.
So even if you manage to make this work, if your data ever changes you going to have to re-visit the code.
In any case if your wanting to see if each array contains the keys it needs to, what I put above would be a more sane way to do it.

PHP retrieving all the type array in the $_FILES array

I want to find a way to drill down into the $_FILES array and retrieve the [type] => Array in its entirety. I have tried a number of approaches can't get anywhere with this:
$result = preg_grep('/\image\b/', $_FILES);
When I output $result in this manner:
echo '<pre>';
print_r($result);
echo '</pre>';
I get the following:
Array (
)
Which is of course useless. I've been going through the Manual, looking at all the array functions, but haven't found anything that works. Is there a PHP function for this? Any help would be very much appreciated!
Cheers,
shackleton
PS I've also tried to use:
foreach ($_FILES['userfile']['type'] as $key => $value) {
to create my own array with both the key and value of each file uploaded. The problem with that is the variable will not create an array with more than one - [0] - index because the array construct is referencing the variable. That seems to be a dead end.
If you're sending multiple files, you should iterate using $_FILES only, as this:
$types=array();
foreach($_FILES as $filename=>$arrayofvalues){
$types[]=$arrayofvalues['type'];
}
Holla Ricardo,
Thanks so much, that works like a charm. I had to go find a way to flatten the resulting array, but did find a function online that works. I had been looking for that function too for several days. Here's what I came up with:
// Create an array of only the file type
$types = array();
foreach ($_FILES as $filename => $arrayofvalues) {
$types[] = $arrayofvalues['type'];
}
// Create a sub-array of types
foreach($types as $subArray) {
foreach($subArray as $val){
$simple[] = $val;
}
}
echo "Simple images array:";
echo '<pre>';
print_r($simple);
echo '</pre>';
"<br />";
// Get the key & value of just image files
$images = preg_grep('/\image\b/', $simple);
// Use the differenc array function to find the indices I want
$dif = array_diff($simple, $images);
echo "Difference:";
echo '<pre>';
print_r($dif);
echo '</pre>';
"<br />";
Of course the print_r() is only so I can see what the code is producing. The output looks like this:
html Output
Thanks again for you assistance!
Cheers,
shackleton
Your approach is a bit heavy-handed with the foreach loops. I have prepared a shorter way to accomplish your task.
Using this array:
$FILES=array(
"file1"=>array("type"=>array("text/plain")),
"file2"=>array("type"=>array("image/tiff")),
"file3"=>array("type"=>array("")),
"file4"=>array("type"=>array("image/png")),
"file5"=>array("type"=>array("image/gif")),
"file6"=>array("type"=>array("image/jpeg"))
);
You can have your output with these two one-liners:
$simple_images=array_column(array_column($FILES,"type"),0);
var_export($simple_images);
echo "\n";
$difference=array_filter($simple_images,function($v){return strpos($v,"image")===false;});
var_export($difference);
Output:
array (
0 => 'text/plain',
1 => 'image/tiff',
2 => '',
3 => 'image/png',
4 => 'image/gif',
5 => 'image/jpeg',
)
array (
0 => 'text/plain',
2 => '',
)
Referring to your preg_grep() function, it is best to avoid using regex when another string manipulation will suffice. This is will improve performance.

PHP scan directory and array

I have a script that scans a folder and put in an array the file names it contains.
Then I shuffle the array and display the file names.
Like this:
$count=0;
$ar=array();
$i=1;
$g=scandir('./images/');
foreach($g as $x)
{
if(is_dir($x))$ar[$x]=scandir($x);
else
{
$count++;
$ar[]=$x;
}
}
shuffle($ar);
while($i <= $count)
{
echo $ar[$i-1];
$i++;
}
?>
It works well but for some reason I get something like this:
fff.jpg
ccc.jpg
Array
nnn.jpg
ttt.jpg
sss.jpg
bbb.jpg
Array
eee.jpg
Of course, the order changes when I refresh the page because of the shuffle I did but among 200 filenames I always get these 2 "Array" somewhere in the list.
What could it be?
Thank you
Just to explain the part wherein it gives you the Array.
First off, scandir returns the following:
Returns an array of files and directories from the directory.
From that return values, it returned this (this is an example, for reference):
Array
(
[0] => . // current directory
[1] => .. // parent directory
[2] => imgo.jpg
[3] => logo.png
[4] => picture1.png
[5] => picture2.png
[6] => picture3.png
[7] => picture4.png
)
Those dots right there are actually folders. Right now in your code logic, when it hits/iterate this spot:
if(is_dir($x))$ar[$x]=scandir($x); // if its a directory
// invoke another set of scandir into this directory, then append it into the array
Thats why your resultant array has mixed strings, and that another extra/unneeded scandir array return values from ..
A dirty quick fix could be used in order to avoid those. Just skip the dots:
foreach($g as $x)
{
// skip the dots
if(in_array($x, array('..', '.'))) continue;
if(is_dir($x))$ar[$x]=scandir($x);
else
{
$count++;
$ar[]=$x;
}
}
Another alternative is to use DirectoryIterator:
$path = './images/';
$files = new DirectoryIterator($path);
$ar = array();
foreach($files as $file) {
if(!$file->isDot()) {
// if its not a directory
$ar[] = $file->getFilename();
}
}
echo '<pre>', print_r($ar, 1);

Trying to put assoociative array back into a flat text file saved as a .csv file

I have created a script that will take a flat text file with 4 bits of information, with commas separating the 4 bits of information, as if it were a csv file, (and I've saved it as such), and it will explode this file into an array, sort the information based on a number (the age of persons), from highest to lowest, and after that I don't have a solution for finishing the script. What I need is to rewrite this array back into the flat file again, now that the information has been properly sorted.
I was thinking either a rewrite or an implode of some kind.
The array looks as such:
Array
(
[0] => Array
(
[name] => john
[age] => 58
[job] => inspector
[salary] => 42000
)
[1] => Array
(
[name] => henry
[age] => 49
[job] => supervisor
[salary] => 38000
)
[2] => Array
(
[name] => monica
[age] => 27
[job] => assistant
[salary] => 29000
)
)
The actual code on my page looks like this:
?php>
$fh = fopen("C:xampp/htdocs/warehouseemplyees.csv", "r");
while(!feof($fh)){
$current = trim(fgets($fh));
$iArray[] = explode(",", $current);
}
$count = count($iArray);
for($x=0;$x<$count;$x++){
$newArray[$x]["name"] = $iArray[$x][0];
$newArray[$x]["age"] = $iArray[$x][1];
$newArray[$x]["job"] = $iArray[$x][2];
$newArray[$x]["salary"] = $iArray[$x][3];
}
function cmp($a, $b)
{
if ($a['age'] == $b['age']) {
return 0;
}
return ($a['age'] > $b['age']) ? -1 : 1;
}
usort($newArray, "cmp");
?>
In the saved flat csv text file, the results look like this:
john,58,inspector,42000
henry,49,supervisor,38000
monica,27,assistant,29000
To conclude. So, once again, I just need to be able to put these results back into the file after this function has sorted them by age highest to lowest. This code works great by the way and the results can be seen in my localhost, but need to get the results back into the file. Thanks for your help.
And please, if you would, be specific with me, I'm very new to programming, and it would help if you told me where to put my specific pieces of information into your code. I can't understand the generic descriptions people often use when talking code. So, if my specific array name goes somewhere or other specific name, please take the time to tell me because I won't know what specific changes to make for my specific application. Please take the necessary pieces from my code above and fill it into your solution so that I'll know. Thanks a bunch!
$fh = fopen("C:xampp/htdocs/warehouseemplyees.csv", "r");
while(!feof($fh)){
$current = trim(fgets($fh));
$iArray[] = explode(",", $current);
}
// You're done reading here
fclose ($fh);
$count = count($iArray);
for($x=0;$x<$count;$x++){
$newArray[$x]["name"] = $iArray[$x][0];
$newArray[$x]["age"] = $iArray[$x][1];
$newArray[$x]["job"] = $iArray[$x][2];
$newArray[$x]["salary"] = $iArray[$x][3];
}
function cmp($a, $b)
{
if ($a['age'] == $b['age']) {
return 0;
}
return ($a['age'] > $b['age']) ? -1 : 1;
}
usort($newArray, "cmp");
// Reopen your file to overwrite with new content : "w". I guess it's the part you were looking for ?
$fh = fopen("C:xampp/htdocs/warehouseemplyees.csv", "w");
foreach ($newArray as $line) {
fputcsv ($fh, $line);
}
fclose ($fh);
You might want to give a look at fputcsv to understand the reading part, then read about fgetcsv to understand how you could have designed your reading part easily.
http://php.net/manual/en/function.fputcsv.php
http://php.net/manual/en/function.fgetcsv.php

While loop in foreach loop not looping correctly

I'm trying to make a very basic php ORM as for a school project. I have got almost everything working, but I'm trying to map results to an array. Here's a snippet of code to hopefully assist my explanation.
$results = array();
foreach($this->columns as $column){
$current = array();
while($row = mysql_fetch_array($this->results)){
$current[] = $row[$column];
print_r($current);
echo '<br><br>';
}
$results[$column] = $current;
}
print_r($results);
return mysql_fetch_array($this->results);
This works, but the while loop only works on the first column. The print_r($results); shows the following:
Array ( [testID] => Array ( [0] => 1 [1] => 2 ) [testName] => Array ( ) [testData] => Array ( ) )
Can anybody shed some light?
Thanks in advance!
It's because you already fetched every row, and the internal pointer is at the end.
The next while, mysql_fetch_array() will immediately return false.
You can reset the pointer to the first row:
mysql_data_seek($this->results, 0);
Put this just before
while($row = mysql_...
I'm not sure you can use the -> operator in a variable name. As you trying to get the key and value out of the array $columns? If so, you want something like this:
foreach($columns as $k => $v) {
//in here, $k is the name of the field, and $v is the associated value
}

Categories