Simplify multiple nested if()'s - php

Can someone help me simplify this complex nested if()'s algorithm? I know it can be simplified, but I'm afraid I'll mess up with the multiple conditions if I trust myself.
$groups = array();
foreach ($items as $item) {
if ($item['group_code']) {
if (array_key_exists($item['group_code'], $groups)) {
if (mb_strlen($groups[$item['group_code']]) < mb_strlen($item['title'])) {
$groups[$item['group_code']] = $item['title'];
}
} else {
$groups[$item['group_code']] = $item['title'];
}
} else {
$groups[$item['item_code']] = $item['title'];
}
}
What I want is to create an index of product titles in $groups. If the group_code key exists for each item, then I want to store the lengthier title of all items belonging to that group. If group_code doesn't exist (meaning it's a single product and not a grouped one), I want to store the title of that item using the item_code instead (this is the simplest condition, and no length comparison is needed here).

What about checking the else conditions first?
foreach ($items as $item) {
if (!isset($item['group_code'])){
$groups[$item['item_code']] = $item['title'];
} else if (!array_key_exists($item['group_code'], $groups)){
$groups[$item['group_code']] = $item['title'];
} else if (mb_strlen($groups[$item['group_code']]) < mb_strlen($item['title'])){
$groups[$item['group_code']] = $item['title'];
}
}

I'd simplify it like this (php 7+):
foreach ($items as $item) {
$t = $item['title'];
$c = $item['group_code'] ?? $item['item_code'];
if (mb_strlen($t) > mb_strlen($groups[$c] ?? '')) $groups[$c] = $t;
}

Related

Outputting odd and even number in array

Using below array, i'm trying to use foreach loop to iterate through each item. Then i need to apply if condition to check if the given number is even and odd. I also need to create two arrays one for even and one for odd and push each number in their respective category.
So i have done this so far:
These are the two arrays i created to push through the values to.
}
$numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
$array_odd = [];
$array_even = [];
foreach ($numbers as $value)
{
if (value %2 == 0)
{
$array_even = $value;
echo $array_even;
}
else
{
$array_odd = $value;
echo $array_odd;
}
I'd like to know if i'm using the correct solution or are there major errors im committing?
It will surely work like charms.
$numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
$array_odd = [];
$array_even = [];
foreach ($numbers as $value)
{
if ($value %2 == 0)
{
$array_even[] = $value;
}
else
{
$array_odd[] = $value;
}
}
echo "<pre>";
print_r($array_odd);
echo "<pre>";
print_r($array_even);

PHP foreach loops and data retrieval

Using PHP and MySQL I have generated two arrays. I would like to loop through these arrays, retrieve data from both and display together in one sentence.
foreach ($items as $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
}
// var_dump($itemTitle);
// string(7) "Halfway" string(5) "Story" string(6) "Listen"
}
foreach ($aData["Items"]["Item"] as $a) {
if (isset($a['description'])) {
$aDescription = $a['description'];
}
// var_dump($aDescription );
// string(4) "Good" string(6) "Strong" string(2) "OK"
}
?>
Desired result;
The title is Halfway and the description is Good.
The title is Story and the description is Strong.
The title is Listen and the description is OK.
// etc
// etc
Is it possible to nest the foreach loops, or is there a better more efficient way?
Please try this way. Hope this help!!
foreach ($items as $index => $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
echo 'The title is '.$itemTitle;
}
if(isset($aData["Items"]["Item"][$index]['description']) {
$itemDescription = $aData["Items"]["Item"][$index]['description'];
echo ' and the description is '.$itemDescription;
}
echo '<br>';
// The title is Halfway and the description is Good.
}
You can merge those two foreach loops using a simple for loop, like this:
$count = count($items) >= count($aData["Items"]["Item"]) ? count($aData["Items"]["Item"]) : count($items);
for($i = 0; $i < $count; ++$i){
if(isset($item[$i]->item_title)) {
$itemTitle = $item[$i]->item_title;
}
if (isset($aData["Items"]["Item"][$i]['description'])) {
$aDescription = $aData["Items"]["Item"][$i]['description'];
}
// your code
}
Sidenote: The above code assumes that two arrays $items and $aData["Items"]["Item"] have unequal number of elements, though this will work for equal number of elements as well. If you're sure that these two arrays will always have equal number of elements, then refactor the $count = ... ; statement in the following way,
$count = count($items);
or
$count = count($aData["Items"]["Item"]);
and use this $count variable in for loop.
Try this hope this will help you out.
Note: Here i am assuming both array's have same indexes.
$items
$aData["Items"]["Item"].
If not you can do array_values($items) and array_values($aData["Items"]["Item"])
foreach ($items as $key => $item)
{
if (isset($item->item_title) && isset($aData["Items"]["Item"][$key]['description']))
{
$itemTitle = $item->item_title;
echo sprinf("The title is %s and the description is %s",$itemTitle,$aData["Items"]["Item"][$key]['description']);
echo PHP_EOL;
}
}

How to check for a value in a string using a foreach loop

This might be a simple solution, however I am not able to come up with it, therefore any help is welcome.
I have a shopping basket so customers can add different items for it (as normal)
On some of these Items there are conditions and when added to the basket I'd like to show them up, however I have it setup so it checks for the value, but it only takes the value from the last added item.
Have the following
public function get_contents() {
$items = array();
foreach($this->items as $tmpItem) {
$item = null;
$item['Condition'] = $this->Conditions[$tmpItem];
$items[] = $item;
}
return $items;
}
foreach($this->items as $item) {
if(strstr($this->Conditions[$item], 'no') ==!false) {
$this->Conditions = 'no';
$item['Condition'] = $this->Conditions;
} else
$this->Conditions = 'yes';
$item['Condition'] = $this->Conditions;
What I would like to do is if any of these items contain the condition 'no'
$this->Conditions = 'no';
$item['Condition'] = $this->Conditions;
However it only takes the value of the last added item
Any help welcome
You are over riding the array element
foreach($this->items as $item) {
if(strstr($this->Conditions[$item], 'no') ==!false){
$this->Conditions = 'no';
$item[] = $this->Conditions;
}
else{
$this->Conditions = 'yes';
$item[] = $this->Conditions;
}
}

Dynamic add to current foreach array

I have a loop that needs to go through each item. So naturally a foreach loop seems like the best idea. However, I need to add an element to the array as it iterates. I tried the following without any luck.
foreach ($allitems as $item) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
I found out the foreach loops seem to use a referenced copy of the array, so editing the array does not register in the loop.
A workaround is to use the older styled while loops as follows:
while (list($key, $item) = each($allitems)) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
Clearly a foreach loop would be nicer and more efficient. Is it possible? Or is the while structure the best possible solution.
Yeah, it is possible:
foreach ($allitems as &$item) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
According to the docs, you need to pass a reference (using the & in front if $item)
More concrete example:
<?php
$allitems = array(1,2,3,4);
foreach ($allitems as &$item) {
echo $item."\n";
if ($item == 2) {
$allitems[] = "Blah";
}
}
?>
This outputs (using php from commandline)
1
2
3
4
Blah
It seems like an ordinary for loop would be best for this:
for ($i = 0; $i < count($array); $i++) {
// Do some stuff here that calculates $value from $array[$i]
if ($value === true) {
$array[] = "New Element";
}
}
You could do foreach...like this....
But it adds more code...so its not any better than your while loop..
foreach($array as $val){
if($val=="check"){$append[]="New Item";}
}
$array = array_merge($array, $append);
Of course, if you want your structure maintained..then rather use array_push

PHP duplicated list

Here is my code to list all category as a list item:
if ($xml) {
foreach($xml->children() as $IRXML) { // SHOW ONLY 5 NEWS ITEMS
foreach($IRXML->children() as $newsrelease) { // EACH NEWSRELEASE IS ONE SUBCHILD
// echo " <div class='news-image'>";
// echo "<img src='/wp-content/themes/bby/images/news-story-01.jpg' alt=''>";
// echo "</div>";
$categories = $newsrelease->Categories;
foreach($categories->children() as $category) {
if ($category != "NA") {
echo "<li class='category ".$category."'>".$category."</li> ";
}
}
}
}
}
What I wanted to do is only to display a category without duplicating it.
$list_cache = array();
if ($xml)
{
foreach($xml->children() as $IRXML)
foreach($IRXML->children() as $newsrelease)
{
$categories = $newsrelease->Categories;
foreach($categories->children() as $category)
{
if ($category != "NA")
{
$print_category = "<li class='category ".$category."'>".$category."</li> ";
if( !in_array($print_category, $list_cache) ) //check if you've stored in previously in this array. In such case, in_array will return true.
{
$list_cache[] = $print_category;
echo $print_category;
}
}
}
}
}
Check out the in_array function from the documentation.
Do you mean you want to display each one only once? If .children() is returning the same child twice, that could be another problem; if it's not something you can change and this is the behavior you're seeing, you could keep an array of category names/ID's, append as you display them, and check the array for duplicates before writing output each time the loop runs.
Assuming there is no way to eliminate the duplicates when generating the XML...that would be more efficient.
You could create an array outside of the loop, and then check to see if a category has already been seen. Example:
$categories = $newsrelease->Categories;
$seen_categories = array();
foreach($categories->children() as $category) {
if ($category != "NA" && !in_array($category,$seen_categories)) {
$seen_categories[]=$category;
echo "<li class='category ".$category."'>".$category."</li> ";
}
}

Categories