HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Search object literal and return first key/value pair that matches regex

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
matchessearchreturnliteralvaluefirstthatandregexobject

Problem

This does what I want:

function test(data){
    for(var key in data){
        if(/_is$/.test(key)){
          var obj = {}
          obj[key] = data[key];
          return obj;
        }
    }
}

test( {a: 'a', user_id_is: '1', b: 'b'} )
> Object {user_id_is: "1"}


But 8 lines of code for such a simple task looks inefficient. Is there a more concise way to achieve such a basic task in JavaScript, something like how Ruby does it?

data.detect {|item| item =~ /_is$/}

Solution

To be fair, the entire thing in Ruby would be a few more method calls:

{:a => 1, :b => 2}.detect { |i| i != :b }.each_slice(2).to_h


Can we do this in a similar number of lines in JavaScript?

First, we can shorten the 8 line original down to 5 lines if we use ES2015 syntax:

function test(data) {
  for(let key of data) {
    if(/_is$/.test(key)) return {[key]: data[key]};
  }
}


Adding in ES2015 methods we can use reduce and an arrow function to get rid of the return at the cost of making this always loop over all the keys in the object (now down to 3 lines):

const test = data => Object.keys(data).reduce((obj, key) =>
  obj || /_is$/.test(key) ? {[key]: data[key]} : undefined, undefined
);


If we're willing to use ES2017, we can use Object.entries and a helper function to get the line count down to 2 at the expense of a little legibility:

const toObj = ([key, value] = []) => key ? {[key]: value} : undefined;
const test = data => toObj(Object.entries(data).find(([key, value]) => /_is$/.test(key)));

Code Snippets

{:a => 1, :b => 2}.detect { |i| i != :b }.each_slice(2).to_h
function test(data) {
  for(let key of data) {
    if(/_is$/.test(key)) return {[key]: data[key]};
  }
}
const test = data => Object.keys(data).reduce((obj, key) =>
  obj || /_is$/.test(key) ? {[key]: data[key]} : undefined, undefined
);
const toObj = ([key, value] = []) => key ? {[key]: value} : undefined;
const test = data => toObj(Object.entries(data).find(([key, value]) => /_is$/.test(key)));

Context

StackExchange Code Review Q#129994, answer score: 2

Revisions (0)

No revisions yet.