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.  
}
10
  • what is x or n? Commented Jun 7, 2019 at 10:10
  • I assume $db_rows is a numerical array since you say you want it inserted directly after $key? Commented Jun 7, 2019 at 10:11
  • X can be 2 or 6, basically a small INT. Commented Jun 7, 2019 at 10:15
  • Yes $db_rows has numerical keys. Commented Jun 7, 2019 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? Commented Jun 7, 2019 at 10:16

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

7 Comments

I mean.. great, but how does this insert into the db after $key whilst maintaining/fixing the incrementation?
Array_fill could remove a loop
@treyBake - The question is about altering an array, not about inserting into the datatabase (or I misread the author's post).
@KévinBibollet check comment chain (unless OP misunderstood me xD)
@treyBake - I think you misunderstood each other comment (you talked about BD, he talked about array only), but let's wait the autor's answer. ;)
|
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;
        } 
    } 
}

4 Comments

This doesn't answer the question, he said he wants the values inserted directly after $key
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.
I also thought of an infinite loop, but it's not the case: because internally, foreach iterates on a copy of the array
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
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.

4 Comments

"this prevents pointer to the array unaffected until the loop ends" - pointer is not disturbed unless you want to
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 let me check ps: you can have second one working well and Fine I have tested and is good in terms on speed.
@johnohod I did check that, as well I have mentioned in points, either you can use array_unshift or array_push.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.