Select data from csv and make associative array I've got a .csv file with ZIP codes containing the city and its sub-districts


67401,City 1,district_a
67401,City 2,district_b
67401,City 3,district_c
67401,City 3,district_d
67401,City 3,district_e
67401,City 3,district_f
67401,City 3,district_g
67401,City 3,district_h
67401,City 3,district_i
67401,City 3,district_j
67401,City 3,district_k
67401,City 3,district_l
67401,City 3,district_m
67401,City 3,district_n
67401,City 3,district_o
67401,City 3,district_p
67401,City 3,district_q
67401,City 3,district_r
67401,City 3,district_s
67401,City 4,district_t
67401,City 5,district_u

67501,City 6,district_v
67501,City 7,district_w
67501,City 8,district_x
67501,City 8,district_y
67501,City 8,district_z

And I need to put it in an array, where I can select/search by the zip code (67401, 67501, etc.) and return these results as an associative array in this format, so I can populate a select control.

For example I want to look-up all the Cities and its districts with zip code 67401 I need this result:

"City 1" =&gt; [
    district_a =&gt; district_a
],
"City 2" =&gt; [
    district_b =&gt; district_b
],
"City 3" =&gt; [
    district_c =&gt; district_c
    district_d =&gt; district_d
    district_e =&gt; district_e
    district_f =&gt; district_f
    district_g =&gt; district_g
    district_h =&gt; district_h
    district_i =&gt; district_i
    district_j =&gt; district_j
    district_k =&gt; district_k
    district_l =&gt; district_l
    district_m =&gt; district_m
    district_n =&gt; district_n
    district_o =&gt; district_o
    district_p =&gt; district_p
    district_q =&gt; district_q
    district_r =&gt; district_r
    district_s =&gt; district_s
],
"City 4" =&gt; [
    district_t =&gt; district_t
],
"City 5" = [
    district_u =&gt; district_u
]


Right now I've got this working code, but I'm sure there has to be a simpler way to achieve it.

&lt;?php 
$zipcode = '67401';

$a = file("zip.csv", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$a = array_map(function ($i) {return explode(',', $i); }, $a);
$a = array_filter($a, function ($i) use ($zipcode) { return $i[0] == $zipcode; });

$b = [];
$i = 0;
foreach ($a as $key =&gt; $value) {
    $b[$i++] = [
        'city' =&gt; $value[1],
        'district'  =&gt; $value[2],
    ];
}

$c = [];

foreach($b as $key =&gt; $item) {
   $c[$item['city']][$key] = $item;
}

ksort($c, SORT_REGULAR);

$d = [];
foreach($c as $key =&gt; $value) {
    $subarray = [];
    foreach($value as $s_key =&gt; $s_val) {
        foreach($s_val as $ss_key =&gt; $ss_val) {
            $subarray[$ss_val] = $ss_val;
        }
    }
    $d[$key] = $subarray;
}

$myresult = $d;
?&gt;
Well, first of all this data must be stored in a database, not a file. Using PDO you'll get your array in a few lines (assuming a database connection is already established):

$sql = "SELECT city, district FROM zip WHERE zipcode=? ORDER BY city, district";
$stmt = $pdo-&gt;prepare($sql);
$stmt-&gt;execute([$zipcode]);
$data = $stmt-&gt;fetchAll(PDO::FETCH_GROUP|PDO::FETCH_COLUMN); 


As of the code present, there are way too much loops to my taste. I believe everything could be done in one loop, like

$zipcode = '67401';
$data = [];
foreach (file("zip.csv", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $row) {
    list($zip, $city, $district) = explode(",",$row);
    if ($zip == $zipcode) {
        if (!isset($data[$city])) {
            $data[$city] = [];
        }
        $data[$city][] = $district;
    }
}


well if you need to sort your arrays, a couple extra loops are still needed

ksort($data);
foreach ($data as $city =&gt; $array) {
    sort($data[$city]);
}