Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>So, the cool thing about <a href="http://c2.com/cgi/wiki?HigherOrderFunction" rel="nofollow noreferrer">higher-order</a> <a href="http://docs.python.org/library/itertools.html" rel="nofollow noreferrer">collection/iterator functions</a> such as <a href="http://api.prototypejs.org/language/Enumerable/prototype/pluck/" rel="nofollow noreferrer">pluck</a>, <a href="http://yuilibrary.com/yui/docs/api/classes/Array.html#method_filter" rel="nofollow noreferrer">filter</a>, <a href="http://underscorejs.org/#each" rel="nofollow noreferrer">each</a>, <a href="http://apidock.com/ruby/Enumerable/map" rel="nofollow noreferrer">map</a>, and friends is that they can be mixed and matched to compose a more complex set of operations.</p> <p>Most languages provide these types of functions (look for packages like collection, iterator, or enumeration/enumerable)...some provide more functions than others and you will commonly see that the functions are named differently across languages (i.e. collect == map, reduce == fold). If a function <a href="http://kourge.net/node/100" rel="nofollow noreferrer">doesn't exist in your language, you can create it</a> from the ones that do exist. </p> <p>As for your test case...we can use <a href="http://php.net/array_reduce" rel="nofollow noreferrer">array_reduce</a> to implement <strong>pluck</strong>. The first version I posted relied on <code>array_map</code>; however, I agree with <a href="https://stackoverflow.com/users/113938/salathe">@salathe</a> that <a href="http://php.net/array_reduce" rel="nofollow noreferrer">array_reduce</a> is more succinct for this task; <a href="http://php.net/array_map" rel="nofollow noreferrer">array_map</a> is an OK option, but you end up having to do more work in the end. <code>array_reduce</code> can look a bit odd at first, but if the callback is neatly organized, all is well.</p> <p>A less naive <code>pluck</code> would also check to see if it can "call" (a function/method) on the iterated value. In the naive implementation below, we assume the structure to be a hash (associative array).</p> <p><strong>This will setup the test-case data (Fixtures):</strong></p> <pre><code>&lt;?php $data[] = array('categoryId' =&gt; 1, 'eventId' =&gt; 2, 'eventName' =&gt; 3, 'vendorName' =&gt; 4); $data[] = array('categoryId' =&gt; 5, 'eventId' =&gt; 6, 'eventName' =&gt; 7, 'vendorName' =&gt; 8); $data[] = array('categoryId' =&gt; 9, 'eventId' =&gt; 10, 'eventName' =&gt; 11, 'vendorName' =&gt; 12); $data[] = array(/* no categoryId */ 'eventId' =&gt; 10, 'eventName' =&gt; 11, 'vendorName' =&gt; 12); $data[] = array('categoryId' =&gt; false,'eventId' =&gt; 10, 'eventName' =&gt; 11, 'vendorName' =&gt; 12); $data[] = array('categoryId' =&gt; 0.0, 'eventId' =&gt; 10, 'eventName' =&gt; 11, 'vendorName' =&gt; 12); </code></pre> <p><strong>Choose the version of pluck you'd prefer</strong></p> <pre><code>$preferredPluck = 'pluck_array_reduce'; // or pluck_array_map </code></pre> <p><strong>"pluck" for PHP 5.3+: array_reduce provides a terse implementation though not as easy to reason about as the array_map version:</strong></p> <pre><code>function pluck_array_reduce($key, $data) { return array_reduce($data, function($result, $array) use($key){ isset($array[$key]) &amp;&amp; $result[] = $array[$key]; return $result; }, array()); } </code></pre> <p><strong>"pluck" for PHP 5.3+: array_map isn't perfect for this so we have to do more checking (and it still doesn't account for many potential cases):</strong></p> <pre><code>function pluck_array_map($key, $data) { $map = array_map(function($array) use($key){ return isset($array[$key]) ? $array[$key] : null; }, $data); // is_scalar isn't perfect; to make this right for you, you may have to adjust return array_filter($map, 'is_scalar'); } </code></pre> <p><strong>"pluck" for legacy PHP &lt;5.3</strong></p> <p>We could have used the legacy <a href="http://php.net/create_function" rel="nofollow noreferrer">create_function</a>; however, it is bad form, not recommended, and also not at all elegant, thus, I've decided not to show it.</p> <pre><code>function pluck_compat($key, $data) { $map = array(); foreach ($data as $array) { if (array_key_exists($key, $array)) { $map[] = $array[$key]; } } unset($array); return $map; } </code></pre> <p><strong>Here we choose a version of "pluck" to call based on the version of PHP we are running. If you run the entire script, you should get the correct answer no matter what version you are on.</strong></p> <pre><code>$actual = version_compare(PHP_VERSION, '5.3.0', '&gt;=') ? $preferredPluck('categoryId', $data) : pluck_compat('categoryId', $data); $expected = array(1, 5, 9, false, 0.0); $variance = count(array_diff($expected, $actual)); var_dump($expected, $actual); echo PHP_EOL; echo 'variance: ', $variance, PHP_EOL; print @assert($variance) ? 'Assertion Failed' : 'Assertion Passed'; </code></pre> <p>Notice there is no ending '?>'. That is because it isn't needed. More good can come of leaving it off than from keeping it around.</p> <p>FWIW, it looks like this is being added to PHP 5.5 as <a href="http://benramsey.com/blog/2013/03/introducing-array-column-in-php-5-dot-5/" rel="nofollow noreferrer">array_column</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload