Home > Software engineering >  add or move key and value to first position in multidimensional array
add or move key and value to first position in multidimensional array

Time:10-22

I have the following array, we'll call it $arr and I have prepared a sample array. I need to manipulate the path $arr['svg'] to have a specific key and value always at index 0 position. This is a sample data-set and depending on the data I'm working with the key's and values are not fixed, however the main point is to always have the title array (key and value) at the top of the svg array.

$arr = array("svg" => 
             array(
                 0 => array("@style" => "overflow:visible", "@xlink:href" => "test.png"),
                 1 => array("g" => "", "@id" => "Layer_2"),
                 2 => array("g" => "", "@id" => "Layer_3"),
                 3 => array("title" => "test")
             ),
             "@version" => 1.2,
             "@baseProfile" => "tiny-ps",
             "@id" => "Layer_1",
             "@xmlns" => "http://www.w3.org/2000/svg"
      );

I am trying to achieve two things under the array path $arr['svg']

  1. If the array key title exists in $arr['svg'] and it is not in index 0 position then move it to index 0 of $arr['svg'] and shift everything else down.
  2. If the array key title DOES NOT exist in $arr['svg'] then add it array('title' => 'test') to index 0 position of $arr['svg'] and shift everything else down.

The expected output of $arr will be like so:

Array
(
    [svg] => Array
        (
            [0] => Array
                (
                    [title] => test
                )
            [1] => Array
                (
                    [@style] => overflow:visible;
                    [@xlink:href] => test.png
                )

            [2] => Array
                (
                    [g] => 
                    [@id] => Layer_2
                )

            [3] => Array
                (
                    [g] => 
                    [@id] => Layer_3
                )

        )

    [@version] => 1.2
    [@baseProfile] => tiny-ps
    [@id] => Layer_1
    [@xmlns] => http://www.w3.org/2000/svg
)

I am trying to use this function to achieve this but it seems this function only works from the root array position $arr, not within a specific path $arr['svg']. If it can be modified to work within a specific path that would hopefully solve the issue.

//source: https://gist.github.com/wpscholar/0deadce1bbfa4adb4e4c
function push_at_to_associative_array($array, $key, $new ){
    $keys  = array_keys( $array );
    $index = array_search( $key, $keys, true  );
    $pos   = false === $index ? count( $array ) : $index   1;
        
    $array = array_slice($array, 0, $pos, true)   $new   array_slice($array, $pos, count($array) - 1, true);
    return $array;
}

Usage:

$title = array("title" => "test');
$arr = push_at_to_associative_array($arr, 'svg', $title);

CodePudding user response:

process the svg array into a new one setting [0] to the default title if we later find a title, replace svg[0]['title'] with the found one, then finally replace the original svg part of the array with the new one.

$arr = [
    "svg" => 
        [
            ["@style" => "overflow:visible", "@xlink:href" => "test.png"],
            ["g" => "", "@id" => "Layer_2"],
            ["g" => "", "@id" => "Layer_3"],
            ["title" => "Fred"]
        ],
        "@version" => 1.2,
        "@baseProfile" => "tiny-ps",
        "@id" => "Layer_1",
        "@xmlns" => "http://www.w3.org/2000/svg"
];

function push_at_to_associative_array(&$arr)
{
    $new_svg = [];
    foreach ($arr['svg'] as $key => $svg){
        if ( $key == 0){
            $new_svg[] = ['title'=>'test'];
        } 
        if ( !array_key_exists('title', $svg) ){
            $new_svg[] = $svg;
        } else {
            # amend title
            $new_svg[0]['title'] = $svg['title'];
        }
    }
    $arr['svg'] = $new_svg;
}

push_at_to_associative_array($arr);
print_r($arr);

RESULTS

Array
(
    [svg] => Array
        (
            [0] => Array
                (
                    [title] => Fred
                )

            [1] => Array
                (
                    [@style] => overflow:visible
                    [@xlink:href] => test.png
                )

            [2] => Array
                (
                    [g] => 
                    [@id] => Layer_2
                )

            [3] => Array
                (
                    [g] => 
                    [@id] => Layer_3
                )

        )

    [@version] => 1.2
    [@baseProfile] => tiny-ps
    [@id] => Layer_1
    [@xmlns] => http://www.w3.org/2000/svg
)

And if you run it without a title in the array

$arr = [
    "svg" => 
        [
            ["@style" => "overflow:visible", "@xlink:href" => "test.png"],
            ["g" => "", "@id" => "Layer_2"],
            ["g" => "", "@id" => "Layer_3"]
        ],
        "@version" => 1.2,
        "@baseProfile" => "tiny-ps",
        "@id" => "Layer_1",
        "@xmlns" => "http://www.w3.org/2000/svg"
];

function push_at_to_associative_array(&$arr)
{
    $new_svg = [];
    foreach ($arr['svg'] as $key => $svg){
        if ( $key == 0){
            $new_svg[] = ['title'=>'test'];
        } 
        if ( !array_key_exists('title', $svg) ){
            $new_svg[] = $svg;
        } else {
            # amend title
            $new_svg[0]['title'] = $svg['title'];
        }
    }
    $arr['svg'] = $new_svg;
}

push_at_to_associative_array($arr);
print_r($arr);

RESULT

Array
(
    [svg] => Array
        (
            [0] => Array
                (
                    [title] => test
                )

            [1] => Array
                (
                    [@style] => overflow:visible
                    [@xlink:href] => test.png
                )

            [2] => Array
                (
                    [g] => 
                    [@id] => Layer_2
                )

            [3] => Array
                (
                    [g] => 
                    [@id] => Layer_3
                )

        )

    [@version] => 1.2
    [@baseProfile] => tiny-ps
    [@id] => Layer_1
    [@xmlns] => http://www.w3.org/2000/svg
)

CodePudding user response:

An easy solution would be to do something like this:

function fix_array( $array ) {
    
    $svg_title_index = array_key_first(
        array_filter( 
            $array['svg'], 
            fn($item) => isset($item['title']) 
        )
    );
    
    if (! $svg_title_index) {
        array_unshift($array['svg'], ['title' => 'test']);
    } elseif($svg_title_index > 0) {
        $value = $array['svg'][$svg_title_index];
        unset($array['svg'][$svg_title_index]);
        
        array_unshift($array['svg'], $value);
    }
    
    return $array;
}

/* CASE 1 - SVG EXISTS BUT IS NOT FIRST */
$array = [
    'svg' => [
        [
            '@style' => 'overflow:visible;',
            '@@xlink:href' => 'test.png'
        ],
        [
            'title' => 'some existing title',
        ],
    ],
    '@version' => '1.2',
    '@baseProfile' => 'tiny-ps',
    '@id' => 'Layer_1',
    '@xmlns' => 'http://www.w3.org/2000/svg'
];

print_r(fix_array( $array ));

/* CASE 2 - SVG DOES NOT EXIST */

$array = [
    'svg' => [
        [
            '@style' => 'overflow:visible;',
            '@@xlink:href' => 'test.png'
        ]
    ],
    '@version' => '1.2',
    '@baseProfile' => 'tiny-ps',
    '@id' => 'Layer_1',
    '@xmlns' => 'http://www.w3.org/2000/svg'
];

print_r(fix_array( $array ));

You can see it in action here

CodePudding user response:

Ok so OP want's to move the array with the title attribute to the start of the array or insert a test value if it doesn't exist.

The below function should achieve this. It might not be the most beautiful or effient but it should put you on the right track.

function order_svg_title( array $input, ?string $default_title ) {

  $position = null;

  // Find position of existing title (if exists).
  foreach( $input[ 'svg' ] as $key => $value ) {
    if ( isset( $value[ 'title' ] ) && $key !== 0 ) {
      $position = $key;
    }
  }

  // Doesn't already exist, add default title (if not null).
  if ( is_null( $position ) ) {
    array_unshift( $input[ 'svg' ], array( 'title' => $default_title ) );
  }

  // Title exists but it's in the wrong position.
  else {
    $value = $input[ 'svg' ][ $position ];
    unset( $input[ 'svg' ][ $position ] );
    array_unshift( $input[ 'svg' ], $value );
  }

  return $input;

}

So for this example usage would be...

$arr = array(
   "svg" => array(
      array(
        "@style" => "overflow:visible",
        "@xlink:href" => "test.png"
      ),
      array(
        array("g" => "", "@id" => "Layer_2"),
        array("g" => "", "@id" => "Layer_3")
      )
   ),
  "@version" => 1.2,
  "@baseProfile" => "tiny-ps",
  "@id" => "Layer_1",
  "@xmlns" => "http://www.w3.org/2000/svg"
);

$new_arr = order_svg_title( $arr, 'test' );

Would return:

Array
(
    [svg] => Array
        (
            [0] => Array
                (
                    [title] => test
                )

            [1] => Array
                (
                    [@style] => overflow:visible
                    [@xlink:href] => test.png
                )

            [2] => Array
                (
                    [0] => Array
                        (
                            [g] => 
                            [@id] => Layer_2
                        )

                    [1] => Array
                        (
                            [g] => 
                            [@id] => Layer_3
                        )

                )

        )

    [@version] => 1.2
    [@baseProfile] => tiny-ps
    [@id] => Layer_1
    [@xmlns] => http://www.w3.org/2000/svg
)

Now with an existing title:

$arr = array(
   "svg" => array(
      array(
        "@style" => "overflow:visible",
        "@xlink:href" => "test.png"
      ),
      array(
        array("g" => "", "@id" => "Layer_2"),
        array("g" => "", "@id" => "Layer_3")
      ),
      array(
        "title" => "In the wrong position. I should be moved."
      )
   ),
  "@version" => 1.2,
  "@baseProfile" => "tiny-ps",
  "@id" => "Layer_1",
  "@xmlns" => "http://www.w3.org/2000/svg"
);

$new_arr = order_svg_title( $arr, 'test' );

Would return:

Array
(
    [svg] => Array
        (
            [0] => Array
                (
                    [title] => In the wrong position. I should be moved.
                )

            [1] => Array
                (
                    [@style] => overflow:visible
                    [@xlink:href] => test.png
                )

            [2] => Array
                (
                    [0] => Array
                        (
                            [g] => 
                            [@id] => Layer_2
                        )

                    [1] => Array
                        (
                            [g] => 
                            [@id] => Layer_3
                        )

                )

        )

    [@version] => 1.2
    [@baseProfile] => tiny-ps
    [@id] => Layer_1
    [@xmlns] => http://www.w3.org/2000/svg
)
  •  Tags:  
  • php
  • Related