0

I've got two arrays, one with IDs and one with Names:

$ids = [4, 13, 6, 8, 10];
$names = ['alice', 'bob', 'charles', 'david', 'elizabeth'];

I need to update the db so that the rows with the ids have the names in the array. Here's the tricky bit: I also have two integers:

$special_name = 2; // the index in $names, in this case we mean 'charles'
$special_id = 13;  // the id value

I don't care about which name goes to which id, except that the name with the $special_name should go on the $special_id.

What's the most elegant way to get there? All of the methods that I'm thinking of seem pretty messy. The best I've thought of is to extract out the special items from each array, and do those first, and then do the rest, perhaps building a new array like this:

$mapped = [];
$mapped[$special_id] = $names[$special_name];
foreach ($ids as $id) {
    if ($id != $special_id) {
        $mapped[$id] = current($names);
    }
    // advance $names pointer
    $next_name = next($names);
    if ($next_name == $special_name) {
        next($names);
    }
}

I haven't tested that yet (I'm about to) but it's meant to produce something like:

$mapped = [
    13 => 'charles',
    4 => 'alice',
    6 => 'bob',
    8 => 'david',
    10 => 'elizabeth'
];

and then running through that to do the actual update. Got a better idea?

4 Answers 4

3

If it wasn't for the special Ids, you could have just array_combine'd the two arrays. Here is how I think to have solved the issue:

Setup

$ids = array(4, 13, 6, 8, 10);
$names = array('alice', 'bob', 'charles', 'david', 'elizabeth');
$specialNameIndex = 2;
$specialId = 13;

Solution

  $result = array($specialId => $names[$specialNameIndex]);
  unset($ids[array_search($specialId, $ids)], 
        $names[$specialNameIndex]);
  $result += array_combine($ids, $names);

Result

print_r($result);
Array
(
    [13] => charles
    [4] => alice
    [6] => bob
    [8] => david
    [10] => elizabeth
)
Sign up to request clarification or add additional context in comments.

7 Comments

Incredible. I was about to post line for line the exact same solution, except feeding 2 args to unset(). creepy lol
@chris even with the same variable names? Oo :D
I thought about using unset, too, but array_combine slipped my mind. That feels a bit better. Cool, didn't know you could add arrays like that. Thx.
ah crap! array_combine requires that both arrays have the same number of elements, which might not necessarily be the case. Either could be longer, we're only mapping as many as we can. Gah!
@Gordon, no, I used the op's variable names.
|
1

You can use array_combine and then set/append your special values:

$mapped = array_combine($ids, $names);
$mapped[$special_id] = $names[$special_name];

2 Comments

This overwrites the existing name at special ID (bob) and then you had charles twice in the array. Also, $special_id is the index of $names and not the name itself.
This answer is provably incorrect and should not have a positive score. 3v4l.org/tl2pS Ideally it should be self-deleted because it has earned points while never being correct.
0

Gordon's answer uses very few function calls to populate the desired result. The approach declares the first associative element in the result according to the special conditions, then removes those elements from the input arrays, then appends the remaining data via array_combine() and the union operator (+).

A less efficient alternative would be to move the specially nominated elements to the front of their respective arrays before calling array_combine() on the reconfigured arrays.


  1. Move an element to the front of its indexed array by its value (when it is guaranteed to exist):

    unset($ids[array_search(13, $ids)]);
    array_unshift($ids, $specialId);
    
  2. Move an element to the front of its indexed array by its index/position (when it is guaranteed to exist):

    array_unshift(
        $names,
        array_splice($names, 2, 1)[0]
    );
    

If you don't want to unset() or array_unshift() on the journey to the desired result in this question, the returned array from array_splice() (the targeted element) can be merged to the front of each respective mutated array inside of an array_combine() call.

Code: (Demo)

var_export(
    array_combine(
        array_merge(array_splice($ids, array_search(13, $ids), 1), $ids),
        array_merge(array_splice($names, 2, 1), $names)
    )
);

Comments

-1

Since you use the default indexes you can use foreach() on keys($ids) to get the indexes so that you can iterate through both arrays at once. Just compare the value of the current index of $ids and use the alternate index of $names when appropriate.

2 Comments

either my comment to @henasraf applies to you as well, or I'm not understanding your solution. Can you provide a bit more (pseudo-)code?
This no implementation hint could have been a comment under the question.

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.