views:

86

answers:

4

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

$ids = array(4, 13, 6, 8, 10);
$names = array('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 ints:

$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 = new array();
$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 = array(13=>'charles', 4=>'alice',6=>'bob', 8=>'david', 10=>'elizabeth');

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

UPDATE: added the possible solution above. Meanwhile a couple answers have come in.

A: 

Are the $ids and $names arrays synced? (Does 4 correspond to 'alice'?)


for ($i=0; $i < count($ids); $i++) {
    $indexed[$ids[$i]] = $names[$i]; // $indexed[4] = 'alice';
    $indexed2[] = array ( $ids[$i] => $names[$i] ); // $indexed[0] = ( 4 => 'alice')
}

Pick your fave

henasraf
4 corresponds to Alice, but 13 is supposed to correspond to Charles, not Bob. That's the point of the question. (Sorry if I wasn't clear.)
sprugman
A: 

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.

Ignacio Vazquez-Abrams
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?
sprugman
I would say the latter, but that's alright.`foreach(keys($id) as $ix)``{`` $n = $names[$ix];`` if ($id[$ix] == $special_id)`` {`` $n = $names[$special_name];`` }`` do_something_with($id[$ix], $n);``}`
Ignacio Vazquez-Abrams
A: 

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

$mapped = array_combine($ids, $names);
$mapped[$special_id] = $names[$special_name];
knittl
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.
Gordon
@gordon here we meet again ;) you are right this time, i upvoted your qestion. (and changed $special_name in my answer to reflect the nature of an index)
knittl
@knittl thx. I'm sure we'll meet more often over time ;) cheers!
Gordon
+2  A: 

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
)
Gordon
Incredible. I was about to post line for line the exact same solution, except feeding 2 args to unset(). creepy lol
chris
@chris even with the same variable names? Oo :D
Gordon
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.
sprugman
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!
sprugman
@Gordon, no, I used the op's variable names.
chris
@sprugman you could array_pad them to an equal length, but I still fail to see what this exercise is for anyway. What usecase are you trying to solve?
Gordon
@Gordon: It's complex and not really worth going into all the details, but I'm trying to overwrite the names in the users table with some data from somewhere else, and I need to make sure the "special" ones get linked. And like I said, either list could be longer. In any case, I used a loop instead of array_combine, which works fine. I gave you the vote even though it doesn't fully solve my actual use case because you answered the question that I asked, and gave me some good ideas...
sprugman