Amjad Khalil
Amjad Khalil

Reputation: 45

Loop an array and retain only elements that relate to a specific key with a qualifying value

I have this array :

(
  [id] => block_5df755210d30a
  [name] => acf/floorplans
  [data] => Array
  (
    [floorplans_0_valid_for_export] => 0
    [floorplans_0_title] => title 1
    [floorplans_0_house_area] => 40m²
    [floorplans_0_bedrooms] => 1
    [floorplans_1_valid_for_export] => 1
    [floorplans_1_title] => title xx
    [floorplans_1_house_area] => 90m²
    [floorplans_1_bedrooms] => 2
    [floorplans_2_valid_for_export] => 1
    [floorplans_2_title] => title 2
    [floorplans_2_house_area] => 50m²
    [floorplans_2_bedrooms] => 1
    [floorplans] => 3

  )
)

As we can see in the data, we have fields (floorplans_X_valid_for_export). What I want to do is to get the data only when this field equal to 1.

So from the given example, I want to keep only these fields:

[floorplans_1_valid_for_export] => 1
[floorplans_1_title] => title xx
[floorplans_1_house_area] => 90m²
[floorplans_1_bedrooms] => 2
[floorplans_2_valid_for_export] => 1
[floorplans_2_title] => title 2
[floorplans_2_house_area] => 50m²
[floorplans_2_bedrooms] => 1

Upvotes: 0

Views: 88

Answers (3)

mickmackusa
mickmackusa

Reputation: 47904

Use a parent loop to check that the number-specific valid_for_export value is non-empty -- since it is either 0 or non-zero.

If so, then just push all of the associated elements into the result array.

Some reasons that this answer is superior to the @Alex's answer are:

  1. Alex's parent loop makes 13 iterations (and the same number of strpos() calls); mine makes just 3 (and only 3 calls of empty()).
  2. $array[$key] is more simply written as $value.
  3. Sanitizing the $key to extract the index/counter is more overhead than necessary as demonstrated in my answer.

Code (Demo)

$array = [
    'floorplans_0_valid_for_export' => 0,
    'floorplans_0_title' => 'title 1',
    'floorplans_0_house_area' => '40m²',
    'floorplans_0_bedrooms' => 1,
    'floorplans_1_valid_for_export' => 1,
    'floorplans_1_title' => 'title xx',
    'floorplans_1_house_area' => '90m²',
    'floorplans_1_bedrooms' => '2',
    'floorplans_2_valid_for_export' => 1,
    'floorplans_2_title' => 'title 2',
    'floorplans_2_house_area' => '50m²',
    'floorplans_2_bedrooms' => 1,
    'floorplans' => 3
];

$labels = ['valid_for_export', 'title', 'house_area', 'bedrooms'];

$result = [];
for ($i = 0; $i < $array['floorplans']; ++$i) {
    if (!empty($array['floorplans_' . $i . '_valid_for_export'])) {
        foreach ($labels as $label) {
            $key = sprintf('floorplans_%s_%s', $i, $label);
            $result[$key] = $array[$key];
        }
    }
}
var_export($result);

Output:

array (
  'floorplans_1_valid_for_export' => 1,
  'floorplans_1_title' => 'title xx',
  'floorplans_1_house_area' => '90m²',
  'floorplans_1_bedrooms' => '2',
  'floorplans_2_valid_for_export' => 1,
  'floorplans_2_title' => 'title 2',
  'floorplans_2_house_area' => '50m²',
  'floorplans_2_bedrooms' => 1,
)

Upvotes: 2

Marek Kus
Marek Kus

Reputation: 150

With that constructed data it might be hard (not impossble tho), hovewer i would suggest to change it to multidimensional arrays so you have something like:

[floorplans][0][valid_for_export] => 0
[floorplans][0][title] => title 1
[floorplans][0][house_area] => 40m²
[floorplans][0][bedrooms] => 1
[floorplans][1][valid_for_export] => 1
[floorplans][1][title] => title xx
[floorplans][1][house_area] => 90m²

Rought sollution

It is not the best approach, but it should work if you dont need anything fancy, and know that structure of data wont change in future

$keys = [];
$for($i=0;$i<$array['floorplans'];++$i) {
    if(isset($array['floorplans_'.$i.'_valid_for_export']) && $array['floorplans_'.$i.'_valid_for_export']===1) {
        $keys[] = $i;
    }
}

print_r($keys);

Upvotes: 0

Alex
Alex

Reputation: 9265

This is an odd schema, but it can be done by iterating through the array and searching for keys where "valid_for_export" equals 1, and then using another array of field "stubs" to get the associated items by a unique identifier of X in floorplans_X_valid_for_export

$array = [
    'floorplans_0_valid_for_export' => 0,
    'floorplans_0_title' => 'title 1',
    'floorplans_0_house_area' => '40m²',
    'floorplans_0_bedrooms' => 1,
    'floorplans_1_valid_for_export' => 1,
    'floorplans_1_title' => 'title xx',
    'floorplans_1_house_area' => '90m²',
    'floorplans_1_bedrooms' => '2',
    'floorplans_2_valid_for_export' => 1,
    'floorplans_2_title' => 'title 2',
    'floorplans_2_house_area' => '50m²',
    'floorplans_2_bedrooms' => 1,
    'floorplans' => 3
];


$stubs = [
     'floorplans_%s_valid_for_export',
     'floorplans_%s_title',
     'floorplans_%s_house_area',
     'floorplans_%s_bedrooms'
];

$newArr = [];

foreach ($array as $key => $value) {
    if (strpos($key, 'valid_for_export') && $array[$key] == 1) {
        $intVal = filter_var($key, FILTER_SANITIZE_NUMBER_INT);
        foreach ($stubs as $stub) {
            $search = sprintf($stub, $intVal);
            if (isset($array[$search])) {
                $newArr[$search] = $array[$search];
            } else {
                // key can't be found, generate one with null
                $newArr[$search] = null;
            }
        }
    }
}

echo '<pre>';
print_r($newArr);

Working: http://sandbox.onlinephpfunctions.com/code/23a225e3cefa2dc9cc97f53f1cbae0ea291672c0

Upvotes: 5

Related Questions