1

Let's say I have the following array

[
        {
            "id": "16",
            "name": "dog",
        },
        {
            "id": "17",
            "name": "cat",
        },
        {
            "id": "18",
            "name": "mouse",
        }
]

I want to use a specific attribute, id as the key for the array. I could do this:

$someArray = [
    ["id" => "16", "name" => "dog"],
    ["id" => "17", "name" => "cat"],
    ["id" => "18", "name" => "mouse"]
];


$newArray = [];
foreach ($someArray as $currItem)
{
    $newArray[$currItem["id"]] = $currItem;
}

Then I would have this (the desired outcome)

{
    "16": {
        "id": "16",
        "name": "dog"
    },
    "17": {
        "id": "17",
        "name": "cat"
    },
    "18": {
        "id": "18",
        "name": "mouse"
    }
}

My question is: is there a better way to do this? Do I really have to loop through every item just to redefine my array ever so slightly?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Keatinge
  • 4,330
  • 6
  • 25
  • 44

2 Answers2

1

I seem to have found a solution using information from Rizier123's answer on another question.

As far as I can tell array_column() is only going to give me an array of ids, so I need to use it with array_combine() and array_values().

$someArray = [
    ["id" => "16", "name" => "a"],
    ["id" => "17", "name" => "b"],
    ["id" => "18", "name" => "c"]
];

$newArray =  array_combine(array_column($someArray, "id"), $someArray);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Keatinge
  • 4,330
  • 6
  • 25
  • 44
1

You beat me to the answer but I might contribute a little anyway...

I'm not sure where your original array is coming from, but if you are decoding JSON, then you can provide a second param to force objects to be converted to associative arrays

$contents = trim(file_get_contents("/home/jaith/foo/foo.json"));
$arr = json_decode($contents, TRUE); // note the second parameter
$v = array_combine(array_column($arr, "id"), $arr); 
var_dump($v);

EDIT: If you can tolerate your output array having objects, this might also work:

$contents = trim(file_get_contents("/home/jaith/foo/foo.json"));
$arr = json_decode($contents);
$v = array_combine(
        array_column(
                array_map(
                        function($item) { return (array)$item; },
                        $arr 
                ),
                "id"
        ),
        $arr
);
var_dump($v);

Keep in mind though that performance could become a concern for very very large arrays. This is doing a lot of array munging.

S. Imp
  • 2,833
  • 11
  • 24
  • Thank you, I'm sure someone will find this helpful. However I'm just showing it as json to make it easier to read. It's actually coming from a MySQL database – Keatinge Jan 07 '17 at 20:46
  • Depending on your MySQL database access method, you can have db records returned as arrays rather than objects -- or simply cast them like $arr = (array)$db_object – S. Imp Jan 07 '17 at 20:47
  • I'm using PDO, I know about PDO::FETCH_ASSOC but I don't know if it's possible to get the id as the key? I use `$results = $query->fetchAll(PDO::FETCH_ASSOC);` – Keatinge Jan 07 '17 at 20:47
  • Worth a try I think. Aside from overall result array, DB layers can typically return each record as numerically indexed array, associatively indexed array (with keys corresponding to db columns) or as an object with properties corresponding to db columns. Might be worth fiddling with your db fetching statements. OR you could use array_map or array_walk to perform some kind of casting. – S. Imp Jan 07 '17 at 20:50
  • 1
    @Keatinge, from [php.net-pdostatement.fetch](http://php.net/manual/en/pdostatement.fetch.php) "*`PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set`*" – Mi-Creativity Jan 07 '17 at 20:50
  • @Mi-Creativity using `FETCH_ASSOC` gives me an array like I posted in the quesiton`, that's how I'm getting this data in the first place, it's not indexed by id – Keatinge Jan 07 '17 at 20:52
  • Your notation for the array at the very top of the page represents a numerically indexed array of objects. I'm not sure, but would imagine that FETCH_ASSOC with PDO would return associative arrays rather than objects. I could be totally wrong about this. – S. Imp Jan 07 '17 at 20:59
  • I edited my answer to provide an additional option that would cast each object element in your input to an array in order to extract its id using array_column. – S. Imp Jan 07 '17 at 21:01
  • @S.Imp the very top of the page is the result of `json_encode($arrReturnedFromPDOFetchAssoc)` – Keatinge Jan 07 '17 at 21:01
  • The json_encode and json_decode functions can often convert PHP associative arrays to Javascript objects and vice-versa. – S. Imp Jan 07 '17 at 21:02