kelaskakap
kelaskakap

Reputation: 131

Sort an associative array with unique values by the values of another indexed array

I have 2 arrays:

[
    'field_bathrooms' => 'Bathrooms',
    'field_bedrooms' => 'Bedrooms',
    'field_king_beds' => 'King Beds',
    'field_kitchen' => 'Kitchen',
    'field_queen_beds' => 'Queen Beds',
    'field_sleeps_max' => 'Sleeps',
    'field_sofa_beds' => 'Sofa Beds',
    'field_sqft' => 'Square Footage',
    'field_twin_beds' => 'Twin Beds',
]

My preferred order:

[
    'Bathrooms',
    'Square Footage',
    'King Beds',
    'Sofa Beds',
    'Sleeps',
    'Twin Beds',
    'Queen Beds',
    'Kitchen',
    'Bedrooms',
]

I want to sort the 1st array by the 2nd array's key, so final result is an array like this:

[
    'field_bathrooms' => 'Bathrooms',
    'field_sqft' => 'Square Footage',
    'field_king_beds' => 'King Beds',
    'field_sofa_beds' => 'Sofa Beds',
    'field_sleeps_max' => 'Sleeps',
    'field_twin_beds' => 'Twin Beds',
    'field_queen_beds' => 'Queen Beds',
    'field_kitchen' => 'Kitchen',
    'field_bedrooms' => 'Bedrooms',
]

Upvotes: 2

Views: 187

Answers (6)

mickmackusa
mickmackusa

Reputation: 47894

  1. array_multisort() is suitable because the keys are non-numeric and will be preserved by default. This script can handle duplicate values in the input array with losing data. Demo

    $order = array_flip($order);
    array_multisort(
        array_map(fn($v) => $order[$v], $array),
        $array
    );
    var_export($array);
    

    If values might not exist in the ordering array, then fall back to PHP_INT_MAX to move unlisted values to the back of the array. There will be secondary sorting for elements moved to the back -- they will be sorted alphabetically to split ties.

    array_map(fn($v) => $order[$v] ?? PHP_INT_MAX, $array)


  2. uasort() can sort the array, preserve keys, and handle duplicated values without data loss. Demo

    $order = array_flip($order);
    uasort(
        $array,
        fn($a, $b) => $order[$a] <=> $order[$b]
    );
    var_export($array);
    

    If values might not exist in the ordering array, then fall back to PHP_INT_MAX to move unlisted values to the back of the array. There will be no secondary sorting for elements moved to the back -- they will be arranged in order of occurrence.

    ($order[$a] ?? PHP_INT_MAX) <=> ($order[$b] ?? PHP_INT_MAX)


  3. Triple-flipping and replacing is suitable for the asked question, but there will be vulnerabilities in fringe cases. If the input array has duplicated values, data will be lost in the first flip. If the ordering array has values not present in the input array, the output will be corrupted with extra unwanted elements. If values being flipped might coalesced by PHP to another type/value, then this is another corruption risk. If there are elements in the input array which are not in the ordering array, they will be moved to the back of the array and kept in their order of occurrence. Demo

    var_export(
        array_flip(
            array_replace(
                array_flip($order),
                array_flip($array)
            )
        )
    );
    

Upvotes: 0

Jonathan Wren
Jonathan Wren

Reputation: 3712

This will do what you want in one line:

$result = array_flip( array_replace( array_flip($arr2), array_flip($arr1) ) );

print_r($result);

To explain: Since you want to sort by the value in the array, and not by the key, we use array_flip to flip the array and value in each of your arrays. Then, we use array_replace to replace the values in the second array with the matching ones from the first array (keeping the current order). Then we use array_flip to put the keys and values back how we started.

Upvotes: 3

Mark Parnell
Mark Parnell

Reputation: 9200

$array1 = array
(
    'field_bathrooms' => 'Bathrooms',
    'field_bedrooms' => 'Bedrooms',
    'field_king_beds' => 'King Beds',
    'field_kitchen' => 'Kitchen',
    'field_queen_beds' => 'Queen Beds',
    'field_sleeps_max' => 'Sleeps',
    'field_sofa_beds' => 'Sofa Beds',
    'field_sqft' => 'Square Footage',
    'field_twin_beds' => 'Twin Beds',
);

$array2 = array
(
    0 => 'Bathrooms',
    1 => 'Square Footage',
    2 => 'King Beds',
    3 => 'Sofa Beds',
    4 => 'Sleeps',
    5 => 'Twin Beds',
    6 => 'Queen Beds',
    7 => 'Kitchen',
    8 => 'Bedrooms',
);

$array3 = array();
foreach ($array2 as $val)
{
  $key = array_search($val, $array1);
  $array3[$key] = $val;
}

var_dump($array3);

Upvotes: 0

Ja͢ck
Ja͢ck

Reputation: 173572

You can write a custom sort function that references a map (inversed second array):

$map = array_flip($second_array);

uasort($first_array, function($a, $b) use ($map) {
    return $map[$a] - $map[$b];
});

print_r($first_array);

See also: array_flip() uasort()

Upvotes: 3

castis
castis

Reputation: 8223

aught to do it

<?

$arr1 = array(
    'field_bathrooms' => 'Bathrooms',
    'field_bedrooms' => 'Bedrooms',
    'field_king_beds' => 'King Beds',
    'field_kitchen' => 'Kitchen',
    'field_queen_beds' => 'Queen Beds',
    'field_sleeps_max' => 'Sleeps',
    'field_sofa_beds' => 'Sofa Beds',
    'field_sqft' => 'Square Footage',
    'field_twin_beds' => 'Twin Beds'
);

$arr2 = array(
    'Bathrooms',
    'Square Footage',
    'King Beds',
    'Sofa Beds',
    'Sleeps',
    'Twin Beds',
    'Queen Beds',
    'Kitchen',
    'Bedrooms',
);

$result = array();
foreach($arr2 as $val)
{
    foreach($arr1 as $k => $v)
    {
        if ($val == $v)
        {
            $result[$k] = $v;
            unset($arr1[$k]);
            break;
        }
    }
}
var_dump($result);

Upvotes: 0

Zeeshan
Zeeshan

Reputation: 3024

your code can be something like this:

$indx;
for ($i = 0; i < Aarray1size; i++)
{

    $key = Array1[i];
    for ($j = 0; j < array2size; j++)
    {
         if(Array2[j] == $key)
          {
                index = j;
          }
    }
    Array1[i] = Array2[index];
    index = 0;

}

Upvotes: 0

Related Questions