1

How can I filter a 2d array by the shared column values in another array then sum the values in another column of the filtered data set?

$hotel = [
    [
        'name' => 'hotel one',
        'hotel_price' => '100',
        'hotel_child_price' => '50'
    ],
    [
        'name' => 'hotel two',
        'hotel_price' => '200',
        'hotel_child_price' => '100'
    ],
    [
        'name' => 'hotel three',
        'hotel_price' => '300',
        'hotel_child_price' => '200'
    ],
];

$user_selected_hotel = [
    [
        'name' => 'hotel one',
        'hotel_price' => '100'
    ],
    [
        'name' => 'hotel three',
        'hotel_price' => '300'
    ]
];

How can I retrieve from the first array the hotel_child_price which the user has selected meaning the sum of 50 and 200 = 250.

The second array represents the user's hotel choice.

My current code:

foreach ( $user_selected_hotel as $lp => $hp) {
    $hotl_slct = $hp;
}

function searchForId($hotl_slct, $hotel) {
    foreach ($hotel as $cust1 => $cust_htl) {
        if ($cust_htl['name'] === $hotl_slct) {
            return $cust1;
        }
    }
    return null;
} 
2
  • 3
    Please edit your question and include what you have tried that is not working as you expect it to. Commented Sep 16, 2019 at 17:44
  • 1
    How does that mean the user selected 200+50? I don't understand... Commented Sep 16, 2019 at 18:22

4 Answers 4

1

You can use array functions to easily achieve your desired result, without for loops:

// Get hotel prices.
$prices = array_column($user_selected_hotel, 'hotel_price');
// Find those records from $hotel whose hotel prices are in prices.
$resultPrices = array_filter($hotel, function($elem) use ($prices) { return in_array($elem['hotel_price'], $prices);});
// Sum them.
$finalResult = array_sum(array_column($resultPrices, 'hotel_child_price'));
// Print result.
echo $finalResult;

An even shorter answer (in lines of code):

$resultPrices = array_filter($hotel, function($elem) use ($user_selected_hotel) { return in_array($elem['hotel_price'], array_column($user_selected_hotel, 'hotel_price'));});
$finalResult = array_sum(array_column($resultPrices, 'hotel_child_price'));

Note: Some of your data are missing ,. Please consider correcting your sample data before running the above snippet.

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

4 Comments

I've used the array functions a lot and they are very useful. But I've also realised they can often do a lot more work than is needed. For example using array_column() will extract the data from all rows, even if you only end up searching the first few.
@NigelRen thank you for your remark, I wasn't aware of the overhead that array_column causes. I will try to improve my answer. But the logic implemented is that first you need to extract all values from $hotel and then filter them according to the values of $user_selected_hotel in order to get the final prices and sum them.
It's not about improving your answer - the answer is fine, it's just about being aware of the code your using and what it does in the background.
And just like that, me banging my head for 2 days straight without sleeping have paid off, You sir have solved the dilemma,Thank you so much
1

I've corrected the source data (missing a few ,'s), but the main thing is about how to find each record.

I've changed the searchForId() method to search for the record (using a simple foreach() and when found, it returns the array element for that name. As it returns the array element, all it does then is to extract the 'hotel_child_price' value and add it to a running total.

$total = 0;
foreach( $user_selected_hotel as $lp => $hp) {
    $total += searchForID($hp['name'], $hotel)['hotel_child_price'];
}
echo $total;

function searchForId($hotl_slct, $hotels ) {
    foreach ( $hotels as $hotel )   {
        if ( $hotel['name'] == $hotl_slct ) {
            return $hotel;
        }
    }
    return null;
} 

Comments

0

I don't think I fully understood what you want. But check if the following is what you are searching for, please:

$hotel = [
    [
        'name' => 'hotel one',
        'hotel_price' => '100',
        'hotel_child_price' => '50'
    ],
    [
        'name' => 'hotel two',
        'hotel_price' => '200',
        'hotel_child_price' => '100'
    ],
    [
        'name' => 'hotel three',
        'hotel_price' => '300',
        'hotel_child_price' => '200'
    ],
];

$user_selected_hotel = [
    [
        'name' => 'hotel one',
        'hotel_price' => '100'
    ],
    [
        'name' => 'hotel three',
        'hotel_price' => '300'
    ]
];

foreach($user_selected_hotel as $selected) {
    $key = array_search($selected['name'], array_column($hotel, 'name'));
    $merge = array_merge($selected, $hotel[$key]);
    $merge['hotel_price'] = $selected['hotel_price'] + $hotel[$key]['hotel_price'];
    return $merge;
}

The line $merge['hotel_price'] = $selected['hotel_price'] + $hotel[$key]['hotel_price']; represents the sum between both 'hotel_price', from $hotel and $user_selected_hotel arrays.

Let me know if this is what you want.

Comments

0

Value-based filtering in a functional style: (Demo)

var_export(
    array_sum(
        array_column(
            array_uintersect(
                $hotel,
                $user_selected_hotel,
                fn($a, $b) => $a['name'] <=> $b['name']
            ),
            'hotel_child_price'
        )
    )
);

Key-based filtering in a functional style: (Demo)

var_export(
    array_sum(
        array_intersect_key(
            array_column($hotel, 'hotel_child_price', 'name'),
            array_column($user_selected_hotel, null, 'name')
        )
    )
);

Foreach loop with selective row destructuring and a lookup array: (Demo)

$lookup = array_column($hotel, 'hotel_child_price', 'name');
$sum = 0;
foreach ($user_selected_hotel as ['name' => $name]) {
    $sum += $lookup[$name];
}
var_export($sum);

Comments

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.