简体   繁体   中英

Another javascript array challenge

Solving another array manipulation, and I'm taking longer than usual to solve this. I need help in combining array values:

var array1 = ["alpha|LJ", "bravo|MH", "charlie|MH", "delta|MF",
              "echo|16", "{foxtrot}|GG", "{golf}|HS"];

var array2 = ["charlie-{golf}-{foxtrot}", "echo-{golf}"]; //some templates

such that the final array be:

final_array = ["alpha-LJ", "bravo-MH", "charlie-HS-GG-MH", "delta-MF",
               "echo-HS-16"];

To make it clear how I arrived with the final_array, alpha, bravo and delta only got their "|" replaced with "-" since they are not found on my array2 template. charlie and echo got the template so the respective values of the {} were replaced based on array1. Array1 honestly is not the best key:value relationship that I could come up for now.

Here are some requirementL:

* Anything in array1 with {} braces are not meant to be templated.
* Keywords in array2 will always have a matching value in array1. 

I've read about jquery .map() and thinking that it is achievable using this, maybe together with Regexp. Hope you'll utilize these. Also, if it helps, final_array can be of any order.

I really need to up my knowledge on these two topics... :|

Thank you in advance.

Edit : Updated to match your output and comment some of the madness. This doesn't feel like it's the most efficient, given the split() done to values at the start and then again at the end...but it works.

function funkyTransform( values, templates ){
  // Make a copy of the array we were given so we can mutate it
  // without rudely changing something passed to our function.
  var result = values.concat();

  // Map {value} entries for later lookup, and throw them out of the result
  var valueMap = {};
  for (var i=result.length-1;i>=0;--i){
    var pair = result[i].split('|');
    if (pair[0][0]=="{"){
      valueMap[pair[0]] = pair[1];
      result.splice(i,1); // Yank this from the result
    }
  }
  console.log(valueMap);
  // {
  //   "{foxtrot}": "GG",
  //   "{golf}":    "HS"
  // }

  // Use the value map to replace text in our "templates", and
  // create a map from the first part of the template to the rest.
  // THIS SHOULD REALLY SCAN THE TEMPLATE FOR "{...}" PIECES
  // AND LOOK THEM UP IN THE MAP; OOPS O(N^2)
  var templateMap = {};
  for (var i=templates.length-1;i>=0;--i){
    var template = templates[i];
    for (var name in valueMap){
      if (valueMap.hasOwnProperty(name)){
        template = template.replace(name,valueMap[name]);
      }
    }
    var templateName = template.split('-')[0];
    templateMap[ templateName ] = template.slice(templateName.length+1);
  }
  console.log(templateMap);
  // {
  //   "charlie": "HS-GG",
  //   "echo":    "HS"
  // }

  // Go through the results again, replacing template text from the templateMap
  for (var i=result.length-1;i>=0;--i){
    var pieces = result[i].split('|');
    var template = templateMap[pieces[0]];
    if (template) pieces.splice(1,0,template);
    result[i] = pieces.join('-');
  }
  return result;
}

var output = funkyTransform( array1, array2 );
console.log(output);
// ["alpha-LJ", "bravo-MH", "charlie-HS-GG-MH", "delta-MF", "echo-HS-16"]

This managed to get your desired output, though I made a few assumptions:

  • Anything in array1 with {} braces are not meant to be templated.
  • Keywords in array2 will always have a matching value in array1 (this can easily be changed, but not sure what your rule would be).

Code:

// This is the main code
var final_array = $.map(array1, function (item) {
    var components = item.split('|');
    // Ignore elements between {} braces
    if (/^\{.*\}$/.test(components[0])) return;
    components[0] = template(components[0]); 
    return components.join('-');
});

// Helper to lookup array2 for a particular string and template it
// with the values from array1
function template(str) {
    var index = indexOfMatching(array2, str, '-');
    if (index == -1) return str;

    var components = array2[index].split('-');
    var result = [str];
    for (var i = 1; i < components.length; i++) {
        result.push(array1[indexOfMatching(array1, components[i], '|')]
            .split('|')[1]);
    }
    return result.join('-');
}

// Helper to for looking up array1 and array2
function indexOfMatching(array, target, separator) {
    for (var i = 0; i < array.length; i++) {
        if (array[i].split(separator)[0] === target) return i;
    }
    return -1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM