Friday 19 September 2014

Answering my first PHP question on Stack Overflow

G'day:
It's really quite interesting. With any CFML question someone might ask me, I am brimming with confidence (or bravado, perhaps), am self-assured, and have no problem either backing myself to be correct, or happy to say "dunno, but I'll find out". I've decided I had better start answering PHP questions on Stack Overflow, as answering questions is a really good way to learn stuff. Especially if one doesn't know the answer to start with.



So, today someone asked this question: "Displaying array chunks in php":

im trying to display a specific chunk of an array where an element is located.

for example, lets say this is my array

Array
(
    [0] => Array
        (
            [1] => a
            [2] => b
            [3] => c
            [4] => d
            [5] => e            
        )

    [1] => Array
        (
            [6] => f
            [7] => g
            [8] => h
            [9] => i
            [10] => j   
        )
)


how do i search the array for the 10th key for example, and choose only the chunk its located in?
It's amazing how quickly answers appear for PHP questions - obviously it's a much bigger community than the CFML one - but I found the quality of answer to be about the same. Read into that comment what you will.

I spotted an "in" for using a technique that hadn't been mentioned yet, so I decided to answer.

I decided to use PHP's equivalent of Array.filter(): array_filter().

Here's the solution in CFML to compare to:

// array_filter.cfm

array = [
    {
        1 = "a",
        2 = "b",
        3 = "c",
        4 = "d"
    },
    {
        5 = "e",
        6 = "f",
        7 = "g"
    },
    {
        8 = "h",
        9 = "i"
    },
    {
        10 = "j"
    }
]


function findChunks(array, key){
    return array.filter(function(struct){
        return struct.keyExists(key)
    })
}

chunk = findChunks(array, 7)

dump(var=chunk)

I've changed the data structure to be an array of structs here, because that's closer to what the PHP code has. Here's the output:

Array
1
Struct
5
stringe
6
stringf
7
stringg

This is correct.

And in contrast the PHP equivalent (I'll omit the array definition to save space):

// array_filter.php
// [...]
function findChunk($array, $key){
    return array_filter($array, function($subArray) use ($key){
        return array_key_exists($key, $subArray);
    });
}

$chunks = findChunk($a, 10);
var_dump($chunks);

Firstly: got PHP is ugly compared to CFML! All thoser bloody dollar signs and underscores. Bleah.

The other thing... I had all sorts of problems getting the closure bit to work... because one has to tell PHP which variables to enclose!! Yikes.

Still: that works quite nicely, IMO, with the following caveat I put in my answer:

Note: this will return multiple chunks if there are multiple chunks with the same key in them (which is entirely possible, depending on your data structure).

If you definitely only wanted the first chunk which matched, array_filter() is possibly doing too much work, as it will traverse the entire outer array whether you need it to or not. That that might matter is down to how big your arrays are.

If performance was more important than clarity of intent, then using a more traditional conditional loop might be more the ticket.
I'm pleased PHP has these iteration functions. I haven't checked them all out yet, but I think I perhaps will, shortly.

Anyway: I half expected to get pilloried for my answer for some reason I just don't know about with PHP, but we'll see. I am moderately pleased I was actually able to answer a question though. Cool.

--
Adam