Paul
Paul

Reputation: 421

Is there better way to split array by key starts with certain string?

I have array for e.g.

$myArray = [
    'id' => 1,
    'code' => '1234',
    'translation_lang_id' => 3,
    'translation_name' => 'Lorem Ipsum',
    'translation_description' => 'My content'
];

Now I need to split it into: first with all keys & values where key starts with translation_ and second with rest so it should finally looks like this:

$translationArray = [
    'translation_lang_id' => 3,
    'translation_name' => 'Lorem Ipsum',
    'translation_description' => 'My content'
];

$baseData = [
    'id' => 1,
    'code' => '1234',
];

Is there better way to do this than loop?

Upvotes: 0

Views: 98

Answers (5)

Progrock
Progrock

Reputation: 7485

You could pluck out the key values you want for one, and then difference the original array to get the other.

<?php

$input = [
    'id' => 1,
    'code' => '1234',
    'translation_lang_id' => 3,
    'translation_name' => 'Lorem Ipsum',
    'translation_description' => 'My content'
];

$translation = array_filter($input, function($k) {
    return strpos($k, 'translation_') === 0;
}, ARRAY_FILTER_USE_KEY);

$base = array_diff_key($input, $translation);

var_dump($translation, $base);

Output:

array(3) {
    ["translation_lang_id"]=>
    int(3)
    ["translation_name"]=>
    string(11) "Lorem Ipsum"
    ["translation_description"]=>
    string(10) "My content"
  }
  array(2) {
    ["id"]=>
    int(1)
    ["code"]=>
    string(4) "1234"
  }

But a loop is probably easier to read and follow:

foreach($input as $k=>$v)
    strpos($k, 'translation_') === 0 
        ? $translation[$k]=$v 
        : $base[$k]=$v;

Upvotes: 1

Rahul
Rahul

Reputation: 18557

Demo Link.

Search for any string replacing it with str and get the data in parts,

$str              = "translation_";
$len              = strlen($str); // upto length for fetching sub string
$translationArray = $baseData = [];
foreach ($input as $key => $value) {
    if (substr($key, 0, $len) == $str) { // checking here
        $translationArray[$key] = $value;
    } else {
        $baseData[$key] = $value;
    }
}

Upvotes: 1

Andreas
Andreas

Reputation: 23958

Not a efficient method but it just for the fun of it.
Here's a one liner :-)

$baseData = array_diff_key($myArray, $translationArray = array_intersect_key($myArray,array_flip(preg_grep("/^translation/", array_keys($myArray)))));

It uses preg_grep on the keys then matches them with array_intersect from the main array.
$baseData is then created as an array_diff_key from $translationArray.

https://3v4l.org/HE5vK

Upvotes: 1

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521289

One brute force approach would be to just iterate your array, and assign elements to the appropriate destination array:

$translationArray = array();
$baseData = array();

foreach ($myArray as $key => $value) {
    if (preg_match("/^translation_/", $key)) {
        $translationArray[$key] = $value;
    }
    else {
        $baseData[$key] = $value;
    }
}

Upvotes: 3

Nick
Nick

Reputation: 147166

You can use array_filter with the ARRAY_FILTER_USE_KEY flag to separate the different elements according to whether the key starts with 'translation_' or not:

$translationArray = array_filter($myArray, 
                                 function ($k) { 
                                     return substr($k, 0, 12) == 'translation_'; 
                                 }, ARRAY_FILTER_USE_KEY);
$baseData = array_filter($myArray, 
                         function ($k) { 
                             return substr($k, 0, 12) != 'translation_'; 
                         }, ARRAY_FILTER_USE_KEY);

var_export($translationArray);
var_export($baseData);

Output:

array ( 
  'translation_lang_id' => 3,
  'translation_name' => 'Lorem Ipsum',
  'translation_description' => 'My content', 
)
array (
  'id' => 1,
  'code' => '1234',
)

Demo on 3v4l.org

Upvotes: 3

Related Questions