2017-01-29 54 views
0

我的步驟的陣列,作爲一個例子的我將使用字母:減少的步驟的陣列,以更小的陣列

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

和合並函數,它需要兩個步驟,並返回一個合併步驟:如果它可以將它們合併或空,如果它不能作爲一個例子,將Concat的連續兩個字母:

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

感謝

+0

能使用澄清,應該合併遞歸? IE「'bcd ...'」?或者只是一個迭代? – Enfyve

+0

是應該的,我會更新我的問題,THX – kofifus

+0

問題應該更有意義,現在 – kofifus

回答

0

我結束了:

var steps = ['f', 'b', 'c', 'd', 'x', 'h', 'i', 'z']; 
 

 
function mergeStep(x, y) { 
 
    if ((x.charCodeAt(x.length - 1) + 1) % 97 == y.charCodeAt(0) % 97) { 
 
    return x + y; 
 
    } else { 
 
    return null; 
 
    } 
 
} 
 

 
function mergeStepsArray(steps, mergeStep) { 
 
    let mergedSteps = []; 
 
    for (let i = 1, step = steps[0]; i <= steps.length; i++) 
 
    step = steps[i] && mergeStep(step, steps[i]) || mergedSteps.push(step) && steps[i] 
 
    return mergedSteps 
 
} 
 

 
alert(mergeStepsArray(steps, mergeStep))

0

你可以嘗試這樣的事情用減少和分裂:

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

 

 
function mergeSteps(s1, s2) { 
 
    return s1.charCodeAt(0) - s2.charCodeAt(0) == 1 ? true : false; 
 
} 
 

 
var step1 = steps.reduce(function(acc, curr, ind, arr){ 
 
    if(ind > 0 && mergeSteps(curr, arr[ind - 1])){ 
 
     acc = acc + curr; 
 
    } 
 
    else { 
 
     acc = acc + "-" +curr; 
 
    } 
 
return acc; 
 
}).split("-"); 
 

 
console.log(step1);

+0

謝謝!我只使用字符串作爲例子,我正在尋找一個通用的mergeStepsArray(steps,mergeSteps)函數,然後可以在這種情況下應用。你能把你的解決方案轉換成這樣嗎? – kofifus

+0

你能給出一個你想要轉換的實際輸入設置和輸出的例子嗎? – poushy

+0

相同的輸入和輸出進行測試做的,但我需要mergeStepsArray邏輯在它的觀點而言(即通過調用mergeSteps)不知道數組元素的類型等 – kofifus

1

即使這項工作步驟是字符串:

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 */ 
}); 
+0

我需要一個mergeStepsArray(步驟,mergeSteps)這是一般並不知道它的參數的具體細節 – kofifus

+0

@kofifus我更新了我的答案。檢查上面的** IN GENERAL **部分! –

+0

THX易卜拉欣.... – kofifus

1

你可以使用這樣的事情

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

function checkStepSingle(x, y){ 
    if((x.charCodeAt(x.length-1)+1) % 97 == y.charCodeAt(0)%97){ 
    return x + y; 
    } 
    else{ 
    return null; 
    } 
} 

function mergeArray(array, mergeSteps){ 
    var returnArray = array.slice(); 
    for(i = 0; i+1 < returnArray.length; i++){ 
    var step = mergeSteps(returnArray[i], returnArray[i+1]); 
    if(step != null){ 
     returnArray[i] = step; 
     returnArray.splice(i+1, 1); 
     i = i-1; 
    } 
    } 

    return returnArray; 
} 
console.log(mergeArray(steps, checkStepSingle)) 
console.log(steps) 

但是,如果你還需要使用大寫字母,你必須數97改爲65

另一種方法 這樣是從後到前。你只需添加元素,如果他們不能與下一個減少。爲了100%確定你應該在開始時添加一個if else語句,以確保你不會遇到空數組。

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

function checkStepSingle(x, y){ 
    if((x.charCodeAt(x.length-1)+1) % 97 == y.charCodeAt(0)%97){ 
    return x + y; 
    } 
    else{ 
    return null; 
    } 
} 

function mergeArray(array, mergeSteps){ 
    var tmpArray = []; 
    var tmp = array[0]; 
    for(i = 0; i+1 < array.length; i++){ 
    var step = mergeSteps(tmp, array[i+1]); 
    if(step != null){ 
     tmp = step; 
    } 
    else{ 
     tmpArray.push(tmp); 
     tmp = array[i+1]; 
    } 
    } 
    tmpArray.push(tmp); 

    return tmpArray; 
} 
console.log(mergeArray(steps, checkStepSingle)) 
console.log(steps) 
+0

我需要一個mergeStepsArray(步驟,mergeSteps)是一般,不知道它的參數 – kofifus

+0

細節,那麼你可以另一個參數添加到mergeArray是函數,並用它來代替mergeSteps的。 – Leo

+0

我不明白你的代碼,有一個從未被調用過的checkStepSingle?看到我的問題 - 我需要一個mergeStepsArray(steps,mergeSteps)函數 – kofifus