Accessing a XML node directly via a key - php

$xml = simplexml_load_file($xmlPath);
$items = $xml->list->item;
...
echo $items[$currentIndex]->asXML();
When I print out $currentIndex on each iteration, I get 0, 1, 2, 3, 4, etc.
When I hard code $items[0]->asXML(); $items[1]->asXML(); $items[2]->asXML(); etc. I get the data I want.
But when I loop like I do in the first code segment, it prints out items 0, 2, 4, etc.
How is that possible and what could be causing this?
Thanks,
Ryan
ADDED INFO:
This is the main part of it:
$totalItems = 45;
$keepItems = 10;
$currentIndex = 0;
while($totalItems > $keepItems)
{
$totalItems -= 1;
print_r($xml->list->item[$currentIndex]);
$currentIndex += 1;
}
I just tried this in a separate file and it worked in that instance:
$xml = simplexml_load_file($xmlPath);
$items = $xml->list->item;
$counter = 45;
$display = 0;
while($counter > 4)
{
echo $items[$display]->asXML();
$display += 1;
$counter -= 1;
}
So something in my other code is making this happen. I will have to look at it some more as well, but it's for sure nothing obvious.
Thanks,
Ryan
ADDED INFO 2:
OK, I determined the line of code that causes this "every other one" syndrome :)
unset($items[$currentIndex]);
The thought was to remove/unset an item once I used the data, but it doesn't seem to work the way I expected -- does anybody have an idea of why? Why is it unsetting something it hasn't displayed?
Thanks,
Ryan

Why is it unsetting something it hasn't displayed? That's not what is happening in your case. When you unset the processed item, the array-data are shift... the former element at index 1 get the index 0, 2 moves to 1 and so on. So if you access $element[1] after you have unset $element[0] you'll get the element that was at position $element[2], because the former $element[1] moved to $element[0] and $element[2] to $element[1].
If you always unset the processed element, you can do it by accessing $element[0] on each iteration an cancel if the array is empty.
// ...
while ($array) { // same as count($array)
$currentElement = $array[0];
// do something
unset($array[0]);
}
// ...

Related

php not able to get array value

I have this problem where I can't get the value from the array in the for loop but I can access it in the while loop.
I can't seem to find a answer online, so help would be much appreciated.
while ($pos = strpos($logTxt, $char, $pos))
{
$t++;
$pos += strlen($char);
$positions[$t] = $pos;
}
for($i = 0; $i < sizeof($positions); $i++)
{
$beginLine = $lastEndLine;
$endLine = $positions[2];
$textToEcho = substr($logTxt,$beginLine,$endLine);
$lastEndLine = $endLine;
}
I think that this could be pretty easily fixed by using a foreach loop instead of a for loop, because it is an array.
foreach($positions as $position) {
$beginLine = $lastEndLine;
$endLine = $position;
$textToEcho = substr($logTxt,$beginLine,$endLine);
$lastEndLine = $endLine;
}
If you want to use a for loop still, I believe your problem is you are only referencing the 3rd position of the array (Key 2, as arrays start at 0), not what the loop is pointing to. You could fix it by doing this
for($i = 0; $i < sizeof($positions); $i++)
{
$beginLine = $lastEndLine;
$endLine = $positions[$i];
$textToEcho = substr($logTxt,$beginLine,$endLine);
$lastEndLine = $endLine;
}
Your $endLine always has third element from array, because of $positions[2]. Try changing it to $positions[$i]
You base problem is using constant index in $positions[2]. But your 1st line in for loop $beginLine = $lastEndLine; will always fail because $lastEndLine is not defined yet. You can use smth like
// beginLine // endLine
$textToEcho = substr($logTxt, $positions[$i-1], $positions[$i]);
of course you need $positions[-1] set to 0 before your first loop or smth like this (it's not clear what's happening before)
UPD I've tried your code and concluded
it will not work at all if $char is the first occurence in $logTxt
it does the nearly the same as explode() function

How to remove an all the elements in an array through iteration

I have an array $scripts_stack = []; that holds arrays:
$array_item = array('script' => $file_parts, 'handle' => $file_name, 'src' => $url);
array_push($scripts_stack, $array_item);
<?php
for ($i = 0; $i < sizeof($scripts_stack); $i++) {
$child_array = $scripts_stack[$i];
if (is_array($child_array)) {
// Do things with $child_array,
// then remove the child array from $scripts_stack when done with (BELOW)
unset($scripts_stack[$i]);
}
}
echo "Array Size : " . (sizeof($scripts_stack)); // AT THE END
However, my attemts only remove half the elements. No matter what I try, it's only half the items that get removed. sizeof($scripts_stack) is always half the size of what it was at the start.
I'm expecting that it would be empty // AT THE END
Why is it that I only get half the elements in the array removed?
Thank you all in advance.
As mentioned in other answers, $i increments but the sizeof() the array shrinks. foreach() is probably the most flexible looping for arrays as it exposes the actual key (instead of hoping it starts at 0 and increments by 1) and the value:
foreach ($scripts_stack as $key => $child_array) {
if (is_array($child_array)) {
// Do things with $child_array,
// then remove the child array from $scripts_stack when done with (BELOW)
unset($scripts_stack[$key]);
}
}
Just FYI, the way you're doing it with for almost works. You just need to establish the count before the loop definition, rather than recounting in the continuation condition.
$count = sizeof($scripts_stack);
for ($i = 0; $i < $count; $i++) { // ...
Still, I think it would be better to just use a different type of loop as shown in the other answers. I'd personally go for foreach since it should always iterate every element even if some indexes aren't present. (With the way you're building the array, it looks like the indexes should always be sequential, though.)
Another possibility is to shift elements off of the array rather than explicitly unsetting them.
while ($child_array = array_shift($scripts_stack)) {
// Do things with $child_array,
}
This will definitely remove every element from the array, though. It looks like $child_array should always be an array, so the is_array($child_array) may not be necessary, but if there's more to it that we're not seeing here, and there are some non-array elements that you need to keep, then this won't work.
You advanced $i while the array is getting shrinked, but in the same time you jump over items in your array.
The first loop is where $i == 0, and then when you removed item 0 in your array, the item that was in the second place has moved to the first place, and your $i == (so you will not remove the item in the current first place, and so on.
What you can do is use while instead of for loop:
<?php
$i = 0;
while ($i < sizeof($scripts_stack)) {
$child_array = $scripts_stack[$i];
if (is_array($child_array)) {
// Do things with $child_array,
// then remove the child array from $scripts_stack when done with (BELOW)
unset($scripts_stack[$i]);
} else {
$i++;
}
}
echo "Array Size : " . (sizeof($scripts_stack)); // AT THE END
May be you can use this script.It's not tested.
foreach($array as $key => $value ) {
unset($array[$key]);
echo $value." element is deleted from your array</br>";
}
I hope , it will help you.
The problem root is in comparing $i with sizeof($scripts_stack). Every step further sizeof($scripts_stack) becomes lower (it calculates at every step) and $i becomes higher.
The workaround may look like this:
<?php
$scripts_stack = [];
$array_item = array('script' => 1, 'handle' => 2, 'src' => 3);
array_push($scripts_stack, $array_item);
array_push($scripts_stack, $array_item);
array_push($scripts_stack, $array_item);
array_push($scripts_stack, $array_item);
array_push($scripts_stack, $array_item);
while (sizeof($scripts_stack) > 0) {
$child_array = array_shift($scripts_stack);
if (is_array($child_array)) {
// Do things with $child_array,
// then remove the child array from $scripts_stack when done with (BELOW)
}
}
echo "Array Size : " . (sizeof($scripts_stack)); // AT THE END
https://3v4l.org/N2p3v

Array with only 10 most recent values

I have an array with multiple elements. I want to keep only the 10 most recent values. So I am reversing the array in a loop, checking if the element is within the first 10 range and if not, I unset the element from the array.
Only problem is that the unset does not work. I am using the key to unset the element, but somehow this does not work. The array keeps on growing. Any ideas?
$currentitem = rand(0,100);
$lastproducts = unserialize($_COOKIE['lastproducts']);
$count = 0;
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
if ($count <= 10) {
echo "item[$key]: $lastproduct <BR>";
}
else {
echo "Too many elements. Unsetting item[$key] with value $lastproduct <BR>";
unset($lastproducts[$key]);
}
$count = $count + 1;
}
array_push($lastproducts, $currentitem);
setcookie('lastproducts', serialize($lastproducts), time()+3600);
I'd use array_slice ( http://php.net/array_slice ) perhaps like:
$lastproducts = unserialize($_COOKIE['lastproducts']);
// add on the end ...
$lastproducts[] = $newproduct;
// start at -10 from the end, give me 10 at most
$lastproducts = array_slice($lastproducts, -10);
// ....
You can use array_splice($input, $offset) function for this purpose.
$last_items_count = 10;
if(count($lastproducts) >= $last_items_count) {
$lastproducts = array_splice($lastproducts, count($lastproducts) - $last_items_count);
}
var_dump($lastproducts);
I hope this code helps.
For more information, here is the documentation:
http://php.net/manual/en/function.array-splice.php
I think a better way to select last 10 is:
$selection = array();
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
$selection[$key] = $lastproduct;
if (count($selection)>=10) break;
}
Finally, $selection will have last 10 (or less) products.
Works great using array_splice and array_slice, thanks! :)
$lastproducts = unserialize($_COOKIE['lastproducts']);
// remove this product from array
$lastproducts = array_diff($lastproducts, array($productid));
// insert product on first position in array
array_splice($lastproducts, 0, 0, $productid);
// keep only first 15 products of array
$lastproducts = array_slice($lastproducts, 0, 15);

Issue with getting data when traversing through an array PHP with a variable

I asked a similar question earlier but I couldn't get a clear answer to my issue. I have a function "isParent" that gets 2 pieces of data. Each 1 of the 2 gets a string separating each value with a , or it just gets a plain int and then checks if the first value given is a parent of the second.
I pull the 2 bits of data in and explode them but when I go through my nested for loop and try to test
$toss = $arr1[$i];
print_r($toss);
It comes up blank. I have no idea what the issue is: Here is the full code of the function...
function isParent($parent, $child)
{
$parentArr = explode(',', $parent);
$childArr = explode(',',$child);
//Explode by Comma here. If array length of EITHER parentArr or childArr > 1 Then throw to an Else
if(count($parentArr) <= 1 && count($childArr) <= 1) //If explode of either is > 1 then ELSE
{
$loop = get_highest_slot(15);
for($i = $loop; $i > 0; $i--)
{
$temp = get_membership_from_slot($i,'id_parent','id_child');
if($temp['id_parent'] == $parent && $temp['id_child'] == $child)
{
return 1;
}
}
}
else //set up a for loop in here so that you traverse each parentArr value and for each iteration check all child values
{
$i = count($parentArr);
$c = count($childArr);
for(;$i >=0;$i--) //Loop through every parent
{
for(;$c >=0;$c--)
{
echo '<br>$i = ';
print_r($i);
echo '<br><br>Parent Arr at $i:';
$toss = $parentArr[$i];
echo $toss;
echo '<br>';
print_r($childArr);
echo '<br><br>';
if(isParent($parentArr[$i],$childArr[$c])) //THIS CAUSES AN INFINITE YES! Learn how to pull an array from slot
{
return 1;
}
}
}
}
return 0;
}
You are missing some code for the slot procedures. Apart from that, you probably need to use a different variable for the inner for loop. because $c will be 0 after the first iteration of $i.
Thanks for the help! The issue was in the recursive call back to the top of the function. It was tossed empty slots and when comparing 2 empty slots it returned a false positive. A quick !empty() check fixed it.

Placing integers into the next available position of an array inside of a for loop

Hi I am attempting to figure out how to iterate through integers, determine if they are prime and then put the primes in one array and the non primes into another.
I have already have the function finished for checking for primes which I will leave out for simplicity. I just can't seem to place the values into different arrays. Here is what I have so far.
Any insight on this is appreciated, I have searched through a lot of previous questions and can't seem to come up with a working answers yet, even though this seems so straight forward.
<?php
$start = 0;
$end = 1000;
$primes = array();
$nonPrimes = array();
for($i = $start; $i <= $end; $i++)
{
if(isPrime($i))
{
//add to the next available position in $primes array;
}
else
{
//add to the next available position in $nonPrimes array;
}
}
?>
array_push maybe?
if(isPrime($i))
{
//add to the next available position in $primes array;
array_push($primes,$i);
}
else
{
//add to the next available position in $nonPrimes array;
array_push($nonPrimes,$i);
}
Use the [] operator to add an element to an array:
if (isPrime($i))
{
$primes[] = $i;
}
else
{
$nonPrimes[] = $i;
}
This will result in arrays like:
$primes[2, 3, 5, 7, 11];
and
$nonPrimes[1, 4, 6, 8, 9, 10];

Categories