title: Using map in Perl to map only if key exists
body: <p>I have a data structure that has been defined like this:</p>
  
  <pre><code>my @columns = (
    {
      db =&gt; 'location',
      dt =&gt; 'location',
      search =&gt; 'location',
    },
    {
      db =&gt; 'name',
      dt =&gt; 'name',
      search =&gt; 'name',
    },
    {
      db =&gt; 'iqs',
      dt =&gt; 'iqs',
    },
  );
  </code></pre>
  
  <p>I am mapping the values of search like so:</p>
  
  <pre><code>@where = map +{ $_-&gt;{search} =&gt; { like =&gt; "\%$global_search\%" } }, @columns;
  </code></pre>
  
  <p>If the key search does not exist, I end up with a data structure that has a bunch of these:</p>
  
  <pre><code>{
      '' =&gt; {
          'like' =&gt; '%pas%'
      }
  },
  </code></pre>
  
  <p>And that completely screws up what I am trying to do. So, I am wondering, since map isn't technically a loop, how can I skip when the key search does not exist?</p>
  
  <p><strong>EDIT:</strong> </p>
  
  <p>Someone below had asked about performance differences between map vs loop, and this piqued my curiosity, so I decided to test it myself. Here are the results:</p>
  
  <p><strong>The Code</strong></p>
  
  <pre><code>#!/usr/bin/env perl
  use strict;
  use warnings;
  use Benchmark qw/cmpthese timethese/;
  
  my $global_search = 'test';
  
  
  my @columns;
  for ( my $i = 0; $i &lt;= 100000; $i++ ) {
      my $hash = {
          db =&gt; "test$i",
          dt =&gt; "test$i",
          search =&gt; "test$i"
      };
      push @columns, $hash;
  }
  
  timethese(-30, {
        mapBuild =&gt; sub {
          my @where = map {
            exists ($_-&gt;{search})
              ? +{ $_-&gt;{search} =&gt; { like =&gt; "\%$global_search\%" } }
              : ()
          } @columns;
        },
        forBuild =&gt; sub {
          my @where;
          foreach (@columns) {
            if (exists $_-&gt;{search}) {
              push @where, +{ $_-&gt;{search} =&gt; { like =&gt; "\%$global_search\%" } } ;
            }
          }
        },
  });
  
  cmpthese(-30, {
        mapBuild =&gt; sub {
          my @where = map {
            exists ($_-&gt;{search})
              ? +{ $_-&gt;{search} =&gt; { like =&gt; "\%$global_search\%" } }
              : ()
          } @columns;
        },
        forBuild =&gt; sub {
          my @where;
          foreach (@columns) {
            if (exists $_-&gt;{search}) {
              push @where, +{ $_-&gt;{search} =&gt; { like =&gt; "\%$global_search\%" } } ;
            }
          }
        },
  });
  </code></pre>
  
  <p><strong>The Results</strong></p>
  
  <blockquote>
    <p>Benchmark: running forBuild, mapBuild for at least 30 CPU seconds...<br>
    forBuild: 32 wallclock secs (31.66 usr +  0.00 sys = 31.66 CPU) @
    980.35/s (n=31038)   mapBuild: 31 wallclock secs (31.58 usr +  0.00 sys = 31.58 CPU) @ 994.21/s (n=31397)
              Rate forBuild mapBuild forBuild 978/s       --      -2% mapBuild 993/s       2%       --</p>
  </blockquote>