1

There are probably lots of array questions. But I couldn't find one that answered this specific problem:

I have an associative array as a result from a database query. I loop trough it with a foreach loop. One of the columns contains a number. If that number is larger than 1, I have to duplicate that row x number of times so that the array will have x similiar rows.

I wonder how to do this?

foreach( $db_rows as $key => $value )
{  
  if( $value["number"] > 1 )
  //DUPLICATE $value and insert x number of times into $db_rows directly after $key.  
}
johnohod
  • 494
  • 5
  • 19
  • what is x or n? – Rahul Jun 07 '19 at 10:10
  • I assume $db_rows is a numerical array since you say you want it inserted directly after $key? – Shardj Jun 07 '19 at 10:11
  • X can be 2 or 6, basically a small INT. – johnohod Jun 07 '19 at 10:15
  • Yes $db_rows has numerical keys. – johnohod Jun 07 '19 at 10:15
  • `into $db_rows directly after $key.` this to mean you want to insert rows directly after the $key row in the DB? – treyBake Jun 07 '19 at 10:16
  • @treyBake - yes. If x is 6, I to have 6 identical rows at the same “place” in the array in stead of 1 row – johnohod Jun 07 '19 at 10:20
  • may be of some use: https://stackoverflow.com/questions/740358/reorder-reset-auto-increment-primary-key – treyBake Jun 07 '19 at 10:30
  • I don't think there's really a way to do this in a safe, automated way.. :/ – treyBake Jun 07 '19 at 10:30
  • @johnohod wait.. looking at the answers, in one place you say insert after $db_rows, but in the comments you said yes to insert rows into the DB - which is it? – treyBake Jun 07 '19 at 10:34
  • This question is both Unclear and Too Broad. We do not have a [mcve] and it is asking for multiple techniques (multiple questions already answered on Stack Overflow). We already have [How to repeat an array in PHP?](https://stackoverflow.com/q/2963777/2943403) – mickmackusa Sep 28 '22 at 08:08

3 Answers3

4

You could declare an empty array before the foreach loop, then populate it thanks to the original, its items' number property and a for loop:

$clone_db_rows = [];

foreach( $db_rows as $key => $value )
{  
    for ($i = 0; $i < $value['number']; $i++) {
        $clone_db_rows[] = $value;
    }
}

Test it here.


@Andreas suggests using array_fill to avoid the nested for statement.

He's right, and you could do this the following way, with array_merge:

$clone_db_rows = [];

foreach( $db_rows as $key => $value )
{  
    $clone_db_rows = array_merge(
        $clone_db_rows,            // Merge the current array with... 
        array_fill(                // ...a newly created one containing...
            0,
            $value['number'],      // ... X items equals to...
            $value                 // ... $value.
        )
    );
}

Test it here.

Kévin Bibollet
  • 3,573
  • 1
  • 15
  • 33
0

Probably something like this :

foreach ($db_rows as $key => $value) {
    if ($value['number'] > 1) {
        for ($i = 0; $i < $value['number'] - 1; $i++) {
            $db_rows[] = $value;
        } 
    } 
}
  • 2
    This doesn't answer the question, he said he wants the values inserted directly after $key – Shardj Jun 07 '19 at 10:16
  • This also __increases__ number of elements in array and finding another `$value['number']` in later elements will add them again, and again and again. So this foreach __never stops__. – u_mulder Jun 07 '19 at 10:18
  • I also thought of an infinite loop, but it's not the case: because internally, _foreach_ iterates on a copy of the array – Geoffray Warnants Jun 07 '19 at 10:32
  • Geoffray is correct. This is not a never ending loop. Foreach uses a copy as he says, a for loop and count() would be a never ending loop. @u_mulder – Andreas Jun 07 '19 at 12:11
0

Direct Approach:

$array = [
    ["a" => "a", "b" => "aa", "number" => 3, "d" => 1],
    ["a" => "b", "b" => "bb", "number" => 1, "d" => 1],
    ["a" => "c", "b" => "cc", "number" => 3, "d" => 1],
];

foreach($array as $key => $value)
{
    if($value['number'] > 1) {
        array_unshift($array , $value, $value);
    }
}

echo "<pre>";
print_r($array);
  • take an array
  • check sub-array["value"] in conditions for true
  • append data at the beginning of the array( use array_push instead of array_unshift to insert at the end of the array)
  • this prevents pointer to the array unaffected until the loop ends
  • op did not mention any specific restrictions.

note:

check onto optimization.

  • EDIT - N+1 times Repeat: + Speed:
$output = [];
$times = 2; # set how many times you want to repeat it,

array_map(function($subArray) use(&$output, $times) {
    if($subArray['number']>1) {
        $output = array_merge($output, array_fill(0, $times, $subArray));
    } else {
        array_push($output, $subArray);
    }
}, $array);

PS: second approach maintains order for repeating values same value can benefit in better examination on it.

kalehmann
  • 4,821
  • 6
  • 26
  • 36
  • "this prevents pointer to the array unaffected until the loop ends" - pointer is not disturbed unless you want to – Rohan Tandel Jun 07 '19 at 10:36
  • I guess this also solves my problem. But the order of the elements is a bit strange. I get 2 "a" => "c" in the start of the array, and 1 at the end. – johnohod Jun 07 '19 at 10:50
  • @johnohod let me check ps: you can have second one working well and Fine I have tested and is good in terms on speed. – Rohan Tandel Jun 07 '19 at 11:02
  • @johnohod I did check that, as well I have mentioned in points, either you can use array_unshift or array_push. – Rohan Tandel Jun 07 '19 at 11:11