Home > Net >  array_splice on JSON array in php
array_splice on JSON array in php

Time:08-21

target array

{"array":[{"Name": "John Doe", "mail": "[email protected]"}, {"Name": "Alex Smith", "mail": "[email protected]"}]}

I now want to insert the $insert between "John Doe" and "Alex Smith"

$insert = array("Name"=>"Thomas Dover", "mail"=>"[email protected]");


$counter = 0;

foreach($target as $x => $val) {

    foreach($val as $key => $v) {

     if ($counter == 0) {
      array_splice($target["array"], 1, 0, $insert);
     }


     }
$counter  ;

}

echo json_encode($target);

CodePudding user response:

You don't need to use the foreach for the insertion:

<?php
$target = json_decode(
    '{
        "array": [
            {
                "Name": "John Doe",
                "mail": "[email protected]"
            },
            {
                "Name": "Alex Smith",
                "mail": "[email protected]"
    
            }
        ]
    }',
    true
);

$insert = [
    'Name' => 'Thomas Dover',
    'mail' => '[email protected]'
];

array_splice(
    $target['array'],
    1,
    0,
    [$insert]
);

echo json_encode($target, JSON_PRETTY_PRINT);

Output:

{
    "array": [
        {
            "Name": "John Doe",
            "mail": "[email protected]"
        },
        {
            "Name": "Thomas Dover",
            "mail": "[email protected]"
        },
        {
            "Name": "Alex Smith",
            "mail": "[email protected]"
        }
    ]
}

Added

In case you want to insert that item after "John Doe", not assuming its position:

foreach ($target['array'] as $index => $item) {
    if ($item['Name'] === 'John Doe') {
        array_splice(
            $target['array'],
            $index   1,
            0,
            [$insert]
        );
        break;
    }
}

Or before "Alex Smith":

foreach ($target['array'] as $index => $item) {
    if ($item['Name'] === 'Alex Smith') {
        array_splice(
            $target['array'],
            $index,
            0,
            [$insert]
        );
        break;
    }
}

Or between "John Doe" and "Alex Smith":

foreach ($target['array'] as $index => $item) {
    if ($item['Name'] === 'John Doe') {
          $index;
        break;
    }
}
for (; isset($target['array'][$index]);   $index) {
    $item = $target['array'][$index];
    if ($item['Name'] === 'Alex Smith') {
        array_splice(
            $target['array'],
            $index,
            0,
            [$insert]
        );
        break;
    }
}

Or if the three need to be consecutive:

foreach ($target['array'] as $index => $item) {
    if ($item['Name'] === 'John Doe') {
        if (
            isset($target['array'][$index 1])
            && $target['array'][$index 1]['Name'] === 'Alex Smith'
        ) {
            array_splice(
                $target['array'],
                $index 1,
                0,
                [$insert]
            );
        }
        break;
    }
}

If you don't like nested if:

$found = false;
foreach ($target['array'] as $index => $item) {
    if ($item['Name'] === 'John Doe') {
        $found = true;
        break;
    }
}
if (
    $found
    && isset($target['array'][$index 1])
    && $target['array'][$index 1]['Name'] === 'Alex Smith'
) {
    array_splice(
        $target['array'],
        $index 1,
        0,
        [$insert]
    );
}

CodePudding user response:

There’s two ways to interpret the question. If it is “how to use array_splice” then Pedro’s answer is perfect. If it is “how to search and insert between two specific items” then the answer gets more complex.

I’ve seen versions of this code written with native functions such as array_search and array_column` however I personally find it unreadable, and I’m not certain if there’s a major performance gain.

This code is pretty heavily commented so I’ll let it speak for itself.

$json = '{"array":[{"Name": "John Doe", "mail": "[email protected]"}, {"Name": "Alex Smith", "mail": "[email protected]"}]}';

$target = json_decode($json, true);

$insert = array("Name"=>"Thomas Dover", "mail"=>"[email protected]");

// We will overwrite $val later so we want a reference
foreach($target as $x => &$val) {
    
    // Temporary array
    $between = [];
    
    // Flag for if/when we find the first person
    $foundStart = false;
    
    foreach($val as $key => $v) {
        
        // If we found the first person previously, and this is our second person
        if($foundStart && 'Alex Smith' === $v['Name']) {
            // Insert
            $between[] = $insert;
            
            // Reset the flag just in case the second person is found again
            $foundStart = false;
        }elseif('John Doe' === $v['Name']){
            
            // Flag that we found the first person
            $foundStart = true;
        }
        
        // No matter what, append our current item to the temp array
        $between[] = $v;
    }
    
    // Overwrite our original loop's variable with our temporary
    $val = $between;
}

// Clean up reference variable so surprises don't happen
unset($val);

echo json_encode($target);

Demo: https://3v4l.org/DnJht

Note: There’s edge cases to handle, too, specifically what if there are duplicates in the source array, or what if the insertion point cannot be determined, but I’ll leave that logic for someone else.

Edit As noted, depending on your actual source array you might be able to just skip the outer loop completely which also removes the need for a reference variable.

$json = '{"array":[{"Name": "John Doe", "mail": "[email protected]"}, {"Name": "Alex Smith", "mail": "[email protected]"}]}';

$target = json_decode($json, true);

$insert = array("Name"=>"Thomas Dover", "mail"=>"[email protected]");

// Temporary array
$between = [];
    
// Flag for if/when we find the first person
$foundStart = false;
    
foreach($target['array'] as $key => $v) {
        
    // If we found the first person previously, and this is our second person
    if($foundStart && 'Alex Smith' === $v['Name']) {
        // Insert
        $between[] = $insert;
            
        // Reset the flag just in case the second person is found again
        $foundStart = false;
    }elseif('John Doe' === $v['Name']){
            
        // Flag that we found the first person
        $foundStart = true;
    }
        
    // No matter what, append our current item to the temp array
    $between[] = $v;
}
    
// Overwrite our original loop's variable with our temporary
$target['array'] = $between;

echo json_encode($target);

Demo: https://3v4l.org/2KPIb

  • Related