I would like to pass in an array that contains a list of directories to scan. I want to iterate over each directory and push its content into another array that I will print out, but for some reason my code is not working. The directories exist and the path is correct. I think it has something to do with how I'm using foreach.
These are the errors I'm getting:
Notice: Undefined index: C:\Users\john\Desktop\files\images\ in
C:\xampp\htdocs\test.php on line 6
Warning: scandir(): Directory name cannot be empty in
C:\xampp\htdocs\test.php on line 6
This is the code:
function test($dir = []) {
foreach($dir as $bar) {
$list = [];
array_push($list, scandir($dir[$bar]));
}
print_r($list);
}
test(["C:\Users\john\Desktop\files\images\\", "C:\Users\john\Desktop\files\images\autumn\\"]);
If anyone can think of a simpler way to do this, please don't hesitate to tell me.
You're on the right track. There are a few changes you need to make though.
function test($dir = []) {
$list = [];
foreach($dir as $bar) {
$list[] = scandir($bar);
}
print_r($list);
}
As noted by #BrianPoole you need to move the $list out of the foreach loop. By having it in the loop, the array is reset with each iteration, resulting in the final array having one element.
In addition, the foreach loop as explained above by #TimCooper does not operate the same as in JavaScript. If you really want to access the keys, you can use the following syntax:
foreach($dir as $key => $bar)
You would then use either $dir[$key] or $bar to access the directory value.
Finally, array_push is an additional function call that in your case is not needed. By simply adding [] PHP will push the new value onto the end of the array.
function test($dir) {
// DEFINE LIST OUT SIDE OF LOOP
$list = array();
// Run checks
if(count($dir) > 0) {
// Loop Through Directory
foreach($dir as $directory) {
// Push into list
array_push($list, array("scanned"=>$directory, "contents" => scandir($directory)));
}
}else {
// If no directories are passed return array with error
$list = array(
"error" => 1,
"message" => "No directories where passed into test()",
);
}
print_r($list);
}
This is how I would do it. It provides a couple checks and sets up the data so you can se it a bit more clear.
Related
Since arrays are not treated as objects in php, I have to manually reference them in order to recursively fill an array or constantly copy the new created/filled arrays from recursive calls.
"return" myRecursiveFunc() is not an option because that would end the function at the wrong time.
One way: Referencing
public function depthFirstSearchInOrder()
{
$list = []; //otherwise php screams that only variables can be referenced (inside traverseInOrder)
//Otherwise I would have passed an empty [] as second parameter
return traverseInOrder($this->root, $list);
}
function traverseInOrder($node, &$list)
{
if ($node->left) {
traverseInOrder($node->left, $list);
}
$list[] = $node->value;
if ($node->right) {
traverseInOrder($node->right, $list);
}
return $list;
}
Second way: Creating/Copying arrays
public function depthFirstSearchInOrder()
{
return traverseInOrder($this->root);
}
function traverseInOrder($node, $list = [])
{
if ($node->left) {
$list = traverseInOrder($node->left, $list);
}
$list[] = $node->value;
if ($node->right) {
$list = traverseInOrder($node->right, $list);
}
return $list;
}
Doesn't the second way eat up way more space?
I'm creating new Arrays for each recursive call which I'm then copying again in $list.
Or am I just confused at the moment?
If I was to traverse this tree
// 9,
// 4, 20
// 1, 6, 15 170
Using the second way
I would start with 9
Go left and call recursive (because of 4)
Go left and call recursive (because of 1)
I fill my empty array with 1 and return the array [1]
I'm back to value 4 where I now assign to $list = [1] (which now is a copy of [1] NOT a reference, right? So the array [1] still exists afterwards somewhere?
I push 4 in the array [1,4] and go right (because of 6)
I push 6 to the array [1,4,6] and return this array [1,4,6]
I'm back to value 4 where I now assign to $list = [1,4,6] (which now is a copy of [1,4,6] NOT a reference, right? So the array [1,4,6] still exists afterwards somewhere?
And so on and so forth...
Back to my question:
Isn't the second way more space hungry? Or am I just confused at the moment?
I'm confusing :S with this script...This script working if there are some file, and I will get the echo like:
|test1.txt|test2.txt|test3.txt|test4.txt
the problem is when doesn't exist any file, the php will get an error:
Warning: asort() expects parameter 1 to be array, null given in htdocs\test\ReadFolder8.php on line 6
Warning: Invalid argument supplied for foreach() in htdocs\test\ReadFolder8.php on line 8
is possible to make a function who look if there are the file, if not, get an echo like "no file found" without error?
<?php
$User = $_GET['User'];
foreach (glob("Myuser/$User/*.txt") as $path) {
$docs[$path] = filectime($path);
} asort($docs); // sort by value, preserving keys
foreach ($docs as $path => $timestamp) {
//print date("d M. Y:|H:i:s |", $timestamp);
print '|'. basename($path) .'' . "" . '';
}
?>
the last thing, I don't understand how works the order for the data creation of file... if I create a new file, the new file will the last of the string...how I can invert the order??
Thank you very much :)
The solution is simple: You need to initialize your variable $docs before you use it to an empty variable like this:
$docs = array(); // <-- create array $docs before use...
foreach (glob("Myuser/$User/*.txt") as $path) {
$docs[$path] = filectime($path);
}
asort($docs); // sort by value, preserving keys
To let the function output an error message instead, if there are no such files, you can simply count the number of array elements using count($docs) and check if it is 0 like this:
if (count($docs) == 0) {
echo "no file found";
}
You can use arsort() instead of asort() to get the latest file as first.
I have created an array list with the following code:
<?php
$ids = array();
if (mysql_num_rows($query1))
{
while ($result = mysql_fetch_assoc($query1))
{
$ids["{$result['user_id']}"] = $result;
}
}
mysql_free_result($query1);
?>
Now, i need to read two elements from the array. The first is the current and the second one is the next element of array. So, the simplified process is the following:
i=0: current_element (pos:0), next_element (pos:1)
i=1: current_element (pos:1), next_element (pos:2)
etc
To do this, i have already written the following code, but i cant get the next element for each loop!
Here is the code:
if (count($ids))
{
foreach ($ids AS $id => $data)
{
$userA=$data['user_id'];
$userB=next($data['user_id']);
}
}
The message i receive is: Warning: next() expects parameter 1 to be array, string given in array.php on line X
Does anyone can help? Maybe i try to do it wrongly.
The current, next, prev, end functions work with the array itself and place a position mark on the array. If you want to use the next function, perhaps this is the code:
if (is_array($ids))
{
while(next($ids) !== FALSE) // make sure you still got a next element
{
prev($ids); // move flag back because invoking 'next()' above moved the flag forward
$userA = current($ids); // store the current element
next($ids); // move flag to next element
$userB = current($ids); // store the current element
echo(' userA='.$userA['user_id']);
echo('; userB='.$userB['user_id']);
echo("<br/>");
}
}
You'll get this text on the screen:
userA=1; userB=2
userA=2; userB=3
userA=3; userB=4
userA=4; userB=5
userA=5; userB=6
userA=6; userB=7
userA=7; userB=8
You get the first item, then loop over the rest and at the end of each loop you move the current item as the next first item ... the code should explain it better:
if (false !== ($userA = current($ids))) {
while (false !== ($userB = next($ids))) {
// do stuff with $userA['user_id'] and $userB['user_id']
$userA = $userB;
}
}
Previous answer
You can chunk the arrays into pairs:
foreach (array_chunk($ids, 2) as $pair) {
$userA = $pair[0]['user_id']
$userB = $pair[1]['user_id']; // may not exist if $ids size is uneven
}
See also: array_chunk()
The line below commented GOAL creates an error. The error is not displayed (just get a white screen) and I do not have access to php.ini to change the settings. I'm quite sure the error is something along the lines of "can not use [] for reading".
How can I get around this? The keys must be preserved and that doesn't seem possible with array_push.
foreach ($invention_values as $value)
{
if( array_key_exists($value->field_name, $array) )
{
//GOAL but creates error: $array[$value->field_name][] = $value->field_value;
//works but only with numeric keys
array_push($array, $value);
}
else $array[$value->field_name] = $value;
}
EDIT: code
EDIT2: Actually I think the error is cause I'm dealing with an object an not an array. What is the object equivalent of
$array[$value->field_name][] = $value ?
Your $array[$value->field_name] is empty, so you can't use [] on it. To initialize it as an array, you have to do the following:
if(!array_key_exists($value->field_name, $array) ){
$array[$value->field_name] = array();
}
$array[$value->field_name][] = $value->field_value;
It contradicts with what you have in your last line, so you have to decide, do you want $array[$value->field_name] be an array or scalar value.
I want to loop through an array with foreach to check if a value exists. If the value does exist, I want to delete the element which contains it.
I have the following code:
foreach($display_related_tags as $tag_name) {
if($tag_name == $found_tag['name']) {
// Delete element
}
}
I don't know how to delete the element once the value is found. How do I delete it?
I have to use foreach for this problem. There are probably alternatives to foreach, and you are welcome to share them.
If you also get the key, you can delete that item like this:
foreach ($display_related_tags as $key => $tag_name) {
if($tag_name == $found_tag['name']) {
unset($display_related_tags[$key]);
}
}
A better solution is to use the array_filter function:
$display_related_tags =
array_filter($display_related_tags, function($e) use($found_tag){
return $e != $found_tag['name'];
});
As the php documentation reads:
As foreach relies on the internal array pointer in PHP 5, changing it within the loop may lead to unexpected behavior.
In PHP 7, foreach does not use the internal array pointer.
foreach($display_related_tags as $key => $tag_name)
{
if($tag_name == $found_tag['name'])
unset($display_related_tags[$key];
}
Instead of doing foreach() loop on the array, it would be faster to use array_search() to find the proper key. On small arrays, I would go with foreach for better readibility, but for bigger arrays, or often executed code, this should be a bit more optimal:
$result=array_search($unwantedValue,$array,true);
if($result !== false) {
unset($array[$result]);
}
The strict comparsion operator !== is needed, because array_search() can return 0 as the index of the $unwantedValue.
Also, the above example will remove just the first value $unwantedValue, if the $unwantedValue can occur more then once in the $array, You should use array_keys(), to find all of them:
$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
unset($array[$key]);
}
Check http://php.net/manual/en/function.array-search.php for more information.
if you have scenario in which you have to remove more then one values from the foreach array in this case you have to pass value by reference in for each:
I try to explain this scenario:
foreach ($manSkuQty as $man_sku => &$man_qty) {
foreach ($manufacturerSkus as $key1 => $val1) {
// some processing here and unset first loops entries
// here dont include again for next iterations
if(some condition)
unset($manSkuQty[$key1]);
}
}
}
in second loop you want to unset first loops entries dont come again in the iteration for performance purpose or else then unset from memory as well because in memory they present and will come in iterations.
There are already answers which are giving light on how to unset. Rather than repeating code in all your classes make function like below and use it in code whenever required. In business logic, sometimes you don't want to expose some properties. Please see below one liner call to remove
public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
if (empty($associativeArray) || empty($keysToUnset))
return array();
foreach ($associativeArray as $key => $arr) {
if (!is_array($arr)) {
continue;
}
foreach ($keysToUnset as $keyToUnset) {
if (array_key_exists($keyToUnset, $arr)) {
unset($arr[$keyToUnset]);
}
}
$associativeArray[$key] = $arr;
}
return $associativeArray;
}
Call like:
removeKeysFromAssociativeArray($arrValues, $keysToRemove);