3

My goal is to efficiently apply a dynamically chosen set of transforms to each element of a matrix. I store the selected functions in an array, then apply each of them in a single pass thru the matrix.

My question is, how can I dynamically create the name of a function that I add to the array of functions?

This fiddle contains my attempt. My question is included in the comment block.

function dynam () {

  var prepend = 'before - ';
  var append = ' - after';
  var whichCase = 'Upper';

  var functionsToApply = [];
  var matrix = [
                   ['aBc', 'DeF'],
                   ['ghi', 'JKL'],
               ];

  var out = 'Initial: ' + matrix.join(' | ');
  document.getElementById('output').innerHTML =  out + '\n';
  console.log(out);

  // Set up transforms
  if (whichCase == 'Lower') {
    functionsToApply.push(function(v) {return v.toLowerCase();});
  } else if (whichCase == 'Upper'){
    functionsToApply.push(function(v) {return v.toUpperCase();});
  }

// How can the function be defined dynamically?
// Perhaps something like:
//  if(['Lower','Upper'].indexOf(whichCase) != -1) {
//    functionsToApply.push(function(v) {'return v.to' + which + 'Case();'});
//  }

  if (prepend && prepend.length > 0 && prepend != 'none') {
    functionsToApply.push(function(v) {return prepend + v;});
  }
  if (append && append.length > 0 && append != 'none') {
    functionsToApply.push(function(v) {return v + append;});
  }

// Apply all of the transforms to each of the elements of the matrix
  matrix = matrix.map(function(row){
    return row.map(function(val) {
      for (var fn = 0; fn < functionsToApply.length; fn++) {
        val = functionsToApply[fn](val);  
      }
      return val;
    })
  }); 

  out = 'Final: ' + matrix.join(' | ');
  document.getElementById('output').innerHTML +=  out + '\n';
  console.log(out);
}

1 Answers1

2

I like to declare my functions in a hash in this case, then you can call them based on the value passed in, which is the key to the hash.

Updated: I've added a way to get the lower/upper function dynamically, and call it.

function dynam(whichCase, prepend, append, matrix) {

 var functionHash = {
  "Lower" : function(v) {return v.toLowerCase();},
  "Upper" : function(v) {return v.toUpperCase();},
  "Prepend" : function(v) {return prepend + v;},
  "Append": function(v) {return v + append;}
 }

// to actually get the case function based on the word passed in, 
// you can do it this way.

 var lowerUpperFunction = String.prototype['to' + whichCase + 'Case'];
 var str = lowerUpperFunction.call("xyz");
 console.log(str);

  var functionsToApply = [];
  
  var out = 'Initial: ' + matrix.join(' | ');
  console.log(out);
 
 // see how we just take the whichCase and make that a call to the hash?
 functionsToApply.push(functionHash[whichCase]);

if (prepend && prepend.length > 0 && prepend != 'none') {
    functionsToApply.push(functionHash["Prepend"]);
  }

if (append && append.length > 0 && append != 'none') {
    functionsToApply.push(functionHash["Append"]);
}

// Apply all of the transforms to each of the elements of the matrix
  matrix = matrix.map(function(row){
    return row.map(function(val) {
      for (var fn = 0; fn < functionsToApply.length; fn++) {
        console.log("applying function to val" + val );
        val = functionsToApply[fn](val);  
      }
      return val;
    })
  }); 

  out = 'Final: ' + matrix.join(' | ');
  return out;
}


  var p = 'before - ';
  var a = ' - after';
  var w = 'Upper';
  var m = [
             ['aBc', 'DeF'],
             ['ghi', 'JKL'],
         ];
  
 console.log( dynam(w, p, a, m) );
nixkuroi
  • 2,259
  • 1
  • 19
  • 25
  • Thank you. While I appreciate the effectiveness of this solution, I'm still wondering if there is a way to use text concatenation to actually create the function name. – Dave in Ohio Apr 06 '17 at 01:51
  • I've added what you want there. Basically, you concatenate the name into the String.prototype like this: var lowerUpperFunction = String.prototype['to' + whichCase + 'Case']; and call it like this: var str = lowerUpperFunction.call("xyz"); – nixkuroi Apr 06 '17 at 05:48
  • Thank you, nixkuroi. That looks like what I was trying for. It's late now, so I'll play with it tomorrow. I appreciate your help! – Dave in Ohio Apr 06 '17 at 06:34