Nested foreach loops for associative array combinations - php

I have an associative array as follows:
$myarray = array('a'=>array(), 'b'=>array(), 'c'=>array(), 'd'=>array());
I want to be able to get all pairs of elements in the array. If it wasn't an associative array, I would use nested for loops, like:
for($i=0; $i<count($myarray); $i++) {
for($j=$i+1; $j<count($myarray); $j++) {
do_something($myarray[$i], $myarray[$j]);
}
}
I have looked at using foreach loops, but as the inner loop goes through ALL elements, some pairs are repeated. Is there a way to do this?
Thanks!

The array_values() function returns an integer-indexed array containing all the values, so you can use it to obtain a list that you can iterate with a for.
Otherwise you can 'destroy' the array this way:
while($k = array_pop($my_array)) {
foreach($my_array as $j){
do_something($k, $j);
}
}

Try:
$keys = array_keys($myarray);
$c = count($myarray);
foreach ($keys as $k => $key1) {
for ($i = $k + 1; $i < $c; $i ++) {
dosomething($myarray[$key1], $myarray[$keys[$i]]);
}
}

Related

remove duplicate arrays in loop

I have an associative array that might contain duplicates. I am trying to loop through the array and compare the current element with the next element in the array. If there is a duplicate, it should be removed.
The code below removes one instance of the element. In the test array I'm using, I have 3 duplicate part numbers, but my code only removes one. I'm left with two. I only want one to remain.
$length = count($items);
for($i = 0; $i < $length -1; $i++){
if($items[$i]['part_number'] == $items[$i+1]['part_number']){
unset($items[$i+1]);
$items = array_values($items);
}
}
What am I doing wrong here?
You need to loop backwards through the array, and delete the current item.
$length = count($items);
for($i = $length - 1; $i > 0; $i--){
if($items[$i]['part_number'] == $items[$i-1]['part_number']){
unset($items[$i]);
}
}
becuase your code is
The $ items value is in the for statement.
if you want unique array, you have to array_unique function
http://php.net/manual/en/function.array-unique.php
In your case after you unset element, $i++ in for loop, you reindexed your array and you skip one element. Add $i-- if you unset item. Or you can reindex your array after for loop.
This is also a very simple example you can start improving with.
<?php
$test = ['sample', 'sample', 'sample', 'not', 'not', 'no', 'no'];
$test2 = [];
$k = 0;
foreach ($test as $key => $value) {
if ($key == 0) {
$test2[$k] = $value;
$k++;
} else {
if ($test2[$k - 1] != $value) {
$test2[$k] = $value;
$k++;
}
}
}
$test = $test2;
var_dump($test);
One dirty hack is to check again if you have a duplicate by decreasing $i.
for($i = 0; $i < $length -1; $i++){
if($items[$i]['part_number'] == $items[$i+1]['part_number']){
unset($items[$i+1]);
$items = array_values($items);
$i--;
}
}
This way it will again test your previous value against next item in array.
So if 0==1, then next time if 0==2.
Your code did 0==1 then (2)==(3).

Multiply two arrays

I have two arrays which I want to multiply and get the final sum. First one is fixed but the second one could have missing elements. For example:
$array1 = array(1, 2, 3, 4, 5);
$array2 = array(1, 3, 5);
Lets say I've got missing elements $array2[1] and $array2[3]. I want to be able to multiply and sum up the rest as:
$sum = array_sum($array1[0] * $array2[0] + $array1[1] * $array2[1] + $array1[2] * $array2[2] + $array1[3] * $array2[3] + $array1[4] + $array2[5]);
Length of arrays may also vary so can't do it the way I've written it above. Any suggestions?
You can complete the array2 missing values as 1, then make the two array have the same length.
$missingKeys = [1,3];
foreach($missingKeys as $k)
{
$array2[$k] = 1;
}
$sum = 0;
foreach($array1 as $k => $v)
{
$sum += $v * $array1[$k];
}
Ok, I didn't use my own advise, but I think this might work?
$total = 0;
foreach ($array1 as $index => $value)
{
if (isset($array2[$index])) $total += $value*$array2[$index];
else $total += $value;
}
echo $total;
The assumption is that all elements of $array2 are present in $array1, but not necessarily the other way around.
As you wrote in your question that the first array is leading (has all the indexes) you only need to iterate over it and eventually multiply with the value from the second array or one:
$sum = 0;
foreach ($array1 as $k => $v) {
$sum += $v * ($array2[$k] ?? 1);
}
Different to the accepted answer, there is no need to manipulate the second array.
If I understood your question properly, and your looking for array multiplication, you could use 2 for loops, iterating one of them and multiplying. Your probably looking for something like this:
for ($i = 0; $i < count($array1); $i++) {
for ($j = 0; $j < count($array2); $j++) {
$sum += $array1[$i] * $array2[$j];
}
}

Object iteration using for loop

Object iteration with foreach is easy:
foreach ($item->attributes as $attribute) {
// echo $attribute->name;
}
.. but I wonder if its possible to do the same with for instead:
for ($j=0; $j < count($item->attributes); $j++) {
// echo $item->attributes->$j->$name ?
}
Although I can create a counter outside foreach and increment it, but just wanted to know if for works for objects.
For reference, the object(s) I'm working with looks like this.
for loops works for arrays which have incremented or decremented numeric index, and for associative arrays you have to use foreach unless you have separate arrays of keys, for example:
$count = count($keys);
for($i=0; $i < $count; $i++) {
echo $arr[$keys[$i]];
}
or you can reindex your assocative arrays, using array_values
$arr = array_values($assoc_array);
$count = count($arr);
for($i=0; $i < $count; $i++) {
echo $arr[$i];
}
for objects, they are properties, which can't be start from numbers, therefore you have to convert your object to array and reindex keys.
$arr = array_values(json_decode(json_encode($object), true));
$count = count($arr);
for($i=0; $i < $count; $i++) {
echo $arr[$i];
}
try to avoid above and use foreach instead.
for ($j=0; $j < count((array)$item->attributes); $j++) {
echo $item->attributes[$j];
}
Is this what you mean? You directly access this object that way, same as above, and you cast it beforehand to count.

PHP build array from variables

So I have a variable which I explode:
$values = explode ('|', $split);
This can contain any number of values from 1 to 10+
I have another big array let's call it $tree. I need to loop round the $values whilst building up an array based on the $tree variable.
E.g:
$newArray = $tree [$values [0]][$values [1]];
But this needs to be done dynamically based on the number of elements in the $values array.
Any ideas?
Thanks
Is this what you're trying to do?
$newArray = array();
foreach($values as $key => $val)
{
$newArray[] = $tree[$val][$values[$key + 1]];
}
You need a foreach loop that goes to every single value you have and then put them in the $tree array something like:
$newArray = array();
foreach($values as $index => $value)
{
$newArray[] = $tree[$value][$value[$index + 1]];
}
create a temporary array from $tree and iterate through the values getting each index:
$result = $tree;
foreach ($values as $val){
$result = $result[$val];
}
This way you go down one level deeper into $tree with each value supplied in $values, and $result holds the value stored in $tree at the point you have reached. For example if you have a navigation tree, $values would be the "breadcrumb" of the current navigation position, and $result is the remaining tree from this point downwards.
I think this is what you want. It goes through pairs of elements of $values, using them as the indexes into $tree to add to $newArray
$newArray = array();
for ($i = 0; $i < count(values); $i += 2) {
$newArray[] = $tree[$values[$i]][$values[$i+1]];
}
$values=array(0, 1, 3);
$tree=array("First", "Second", "Third", "Fourth");
$newarray=array();
for ($i=0; $i<count($values); $i++)
{
$newarray[]=$tree[$values[$i]];
}
echo(implode($newarray,", "));
Something like that what you were looking for?

Counting elements in multidimensional array?

I'm trying to count the nested elements in a multidimensional array. At first I thought I could use COUNT_RECURSIVE, but that counts everything. So I've tried two different approaches, none of them appeal to me. Is there a better way to do it?
$count = 0;
foreach ($topics as $t) {
foreach ($t as $c) {
$count++;
}
}
echo $count;
// or
echo (count($topics, COUNT_RECURSIVE)-count($topics));
function countNested($arr) {
return (count($arr, COUNT_RECURSIVE) - count($arr));
}
I would write this code:
$count = 0;
foreach ($topics as $t) {
$count+= count($t);
}
echo $count;
//The following example will count either one-dimensional or two-dimensional arrays
$values_count = (count($values, COUNT_RECURSIVE) - count($values)?:count($values));

Categories