javascript - 将步骤数组减少为更小的数组

标签 javascript ecmascript-6

我有一系列步骤,例如我将使用字母:

let steps=['f', 'b', 'c', 'd', 'x', 'h', 'i' ]

还有一个合并函数,它需要两个步骤,如果可以合并它们,则返回一个合并步骤,如果不能,则返回 null,例如,它将连接两个连续的字母:

function nextLetter(s){
    return s.replace(/([a-zA-Z])[^a-zA-Z]*$/, function(a) {
        var c= a.charCodeAt(0);
        if (c===90 || c===122) return null; else return String.fromCharCode(++c);
        }
    });
}

// merge('x', 'a') -> null , marge('x', 'y') -> 'xy'
function mergeSteps(s1, s2) {
   if (s2==nextLetter(s1)) return s1+s2; else return null;
}

我现在需要写一个mergeStepsArray函数,这将接收一个步骤数组,并通过尝试合并尽可能多的后续步骤来返回一个新数组,以便考虑上面的步骤数组:

mergeStepsArray(steps, mergeSteps);将返回['f', 'bcd', 'x', 'hi' ]

如何高效地编写这样的函数?我尝试使用 Array.reduce 但在这种情况下无法让它工作。

注意:我需要 mergeStepsArray(steps, mergeSteps)这是一般并且不知道其论点的细节。例如,步骤可以由数字组成,mergeSteps 可以 return s2==s1*2 ? s1*s2 : null

谢谢

最佳答案

即使步骤是字符串,这也能工作:

let steps=['f', 'b', 'c', 'd', 'xgoog', 'h', 'i', 'd' ];

// check if the first character of b is just next the last character of a
function valid(a, b) {
  return a.charCodeAt(a.length - 1) + 1 === b.charCodeAt(0);
}


let result = [];
// the first entry of steps as the current a
let current = steps[0];
for(var i = 1; i < steps.length; i++) {
  // if this step is valid add it to current to accumulate the result
  if(valid(current, steps[i]))
    current += steps[i];
  // if not then push the accumulated result into the array, and start another one from this step
  else {
    result.push(current);
    current = steps[i];
  }
}
// push the last one
result.push(current);


console.log(result);

一般情况:

逻辑应该是这样的:

// reduceArray should take three parameters: 
//  * arr: the array,
//  * check: the function responsible for the decision wether to merge or not (takes two parameters and check if they're mergeable)
//  * merge: the function that merges two elements (takes two parameters, merges them and return the result)
function reduceArray(arr, checkFn, mergeFn) {
    // check for errors
    if(!arr || !(arr instanceof Array) || arr.length == 0) return [];
    if(!checkFn || typeof checkFn != "function") return [];
    if(!mergeFn || typeof mergeFn != "function") return [];

    var result = [];

    // current should take the value of the first item in the array so ...
    var current = arr[0];
    // the loop starts at 1
    for(var i = 1; i < arr.length; i++) {
        // always check if current is mergeable with arr[i]
        if(checkFn(current, arr[i])){
            // if so, store the merge result in current and re-check again for the next element
            current = mergeFn(current, arr[i]);
        }
        else {
            // if not store the result, and start another check-merge starting from this index (arr[i])
            result.push(current);
            current = arr[i];
        }
    }
    // don't forget to store the last element (merged or not)
    result.push(current)

    return result;
}


function myCheck(a, b) {
    /* check if a could be merged with b */
    /* must return true or false */
}

function myMerge(a, b) {
    /* merge a with b and return the result */
}

// and then call reduceArray like this:
var myArr = new Array();
// ...
var result = reduceArray(myArr, myCheck, myMerge);
// or like this
var result = reduceArray(myArr, function(a, b){
    /* return true or false depending on whether a and b are mergeable or not */
}, function(a, b){
    /* merge a and b and return the result */
})

另一种方法:

我还添加了对回调的检查(以查看它是否是有效的回调)。

// reduceArray should take three parameters: 
//  * arr: the array,
//  * mergeStepsFn: takes two parameter and return the result if they're mergeable, null othrwise
function reduceArray(arr, mergeStepsFn) {
    // check for errors
    if(!arr || !(arr instanceof Array) || arr.length == 0) return [];
    if(!mergeStepsFn || typeof mergeStepsFn != "function") return [];

    var result = [];

    var current = arr[0];
    for(var i = 1; i < arr.length; i++) {
        // get the result of merging current with the arr[i]
        var mergeResult = mergeStepsFn(current, arr[i]);
        // if merge was successful
        if(mergeResult !== null){ // should compare against null since we have no idea about the data types
            // if so, store the merge result in current
            current = mergeResult;
        }
        else {
            // if not store the accumulated result, and start another check-merge starting from this index (arr[i])
            result.push(current);
            current = arr[i];
        }
    }
    // don't forget to store the last element (merged or not)
    result.push(current)

    return result;
}


function myMergeStepsFunction(a, b) {
    /* if a is mergeable with b then return the merge result, if not return null */
}

// and then call reduceArray like this:
var myArr = new Array();
// ...
var result = reduceArray(myArr, myMergeStepsFunction);
// or like this
var result = reduceArray(myArr, function(a, b){
    /* if a is mergeable with b then return the merge result, if not return null */
});

关于javascript - 将步骤数组减少为更小的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41927010/

相关文章:

运行 onload 和 onchange 的 javascript

javascript - 修改选择,选择单词,然后重新附加插入位置

javascript - jQuery 省略了 params() 和 ajax() 中的日期值

javascript - 在类方法中使用 Promise

javascript - ES6 类和类实例作为构造函数中的参数

JavaScript 类构造函数 - 构造函数是否被称为父级?

Javascript 导出类,而不仅仅是在索引文件中引用它们

javascript - 如何在 Three.js 中一次仅加载一个模型?

javascript - 谷歌地图上的信息窗口无法正常工作

javascript - 对返回带有许多粗箭头的多个函数的 javascript 函数感到困惑