2012-12-31 20 views
2

請參見下面的僞代碼片段近似於我的情況:在複雜例程中使用多個值的最簡單方法?

function foo() { 
    for (velocity=0; velocity<100; velocity++) { 
    root1 = computeRoot1(); 
    root2 = computeRoot2(); 
    // do a bunch of computation with root1 
    // if result of computation is undesirable, do computations again with root2 
    } 

所以,基本上我想做的for循環體中的計算與root1,然後root2如果root1的計算結果是無效的。

我的第一個直覺是明顯的方法,將計算包裝在幫助函數中,但我不確定這是最明確的方法。我正在嘗試在我的代碼中對信息進行良好的搭配,並且對於最多執行兩次(每次迭代)的代碼的函數調用會在不提供大量簡明代碼的情況下擊敗該目標。

我在想也許for循環,如:

for (root=root1; root1IsInvalid==true || bothRootsInvalid==true; root=root2) 

或者具有類似功能的while。但我肯定對其他建議持開放態度

有人讀這段代碼時,哪種方法會使它對您最具可讀性和簡潔性?另外,我正在用JavaScript編寫這個特定的函數,但語言不可知的解決方案將會非常棒。

編輯:澄清代碼片段

回答

3

你有幾個基本的方法:

  1. 把值在數組中,並使用for循環到陣列中運行,在每個項目相同的代碼,可能停止滿足某些條件時的迭代。
  2. 創建一個函數,執行計算,然後只編寫調用第一個函數的代碼,然後編寫第二個函數等等。
  3. 創建一個while循環並重復您的代碼,直到滿足某些條件。

第一個選項更容易擴展到N個項目。第二種選擇對於兩個項目可能更簡單。

您可以使計算函數成爲本地函數(在您當前正在執行的函數中聲明和使用),因此它不會添加到全局名稱空間,並且代碼仍然更加封裝。

我也不能確定你打算用這條線做什麼:

root1, root2 = computeRoots(); 

但是,它只是分配值root2,它看起來像你可能想在var這些前面將它們定義爲局部變量。

+0

有一個權衡的意義,首先是共同計算,所以你總是做兩次工作,而後者則只能在重新計算首先是「無效」。對? –

+0

@JaredFarrish - 大概你可以在'for'循環中測試一些條件,並決定是否繼續進行額外的迭代 - 如果完成了,就會退出'for'循環。 – jfriend00

+0

@ jfriend00感謝您的輸入,我認爲#1是我正在尋找的。此外,爲了清晰起見,更新了我的代碼片段 –

1

如果渴望評估是好的,你可以將你的根收集到一個數組中,並使用roots.filter(isinvalid)來取出無效的值;那麼只需使用結果數組中的第一項。

如果您需要延遲計算,可以概括成懶洋洋地評估一個數組,直到一個非空的結果如下功能的功能,這是發現:

// call fn on items in arr until fn returns non-null 
// returns [item, result] 
// if result===false, no true value was returned 
function firstNotNull(fn, arr) { 
    var i, length, item, result=null; 
    for (i = 0, length=arr.length; i < length; i++) { 
     item = arr[i]; 
     result = fn(item); 
     if (result!==null) { 
      break; 
     } 
    } 
    return [item, result]; 
} 


function rootComputations(root) { 
    var computationResult = null; 
    if (root==1) { 
     computationResult = 1; 
    } 
    return computationResult; 
} 

function computeRoots() { 
    return [0,1]; 
} 

function foo() { 
    var velocity, roots, root, result, computations; 
    for (velocity = 0; velocity < 100; velocity++) { 
     roots = computeRoots(); 
     computations = firstNotNull(rootComputations, roots); 
     console.log(computations); 
     root = computations[0]; 
     result = computations[1]; 
    } 
} 

foo(); 

可以概括firstNotNull()更進一步:

// call fn on items in arr until cond(fn(item)) returns true 
// returns [item, fn(item)], or null if unsatisfied 
function firstSatisfying(cond, fn, arr) { 
    var i, length, item, fnitem, result=null; 
    for (i = 0, length=arr.length; i < length; i++) { 
     item = arr[i]; 
     fnitem = fn(item); 
     if (cond(fnitem)) { 
      result = [item, fnitem]; 
      break; 
     } 
    } 
    return result; 
} 

var firstNotNull = firstSatisfying.bind(null, function(item){return item!==null;}); 

您現在有一個通用函數,用於獲取滿足所需條件的列表中的第一個。

的ECMAScript 5中添加了許多方法,這使得渴望功能應用在陣列更容易,但JavaScript並沒有任何本地設施評價。如果這是你認爲你經常需要的東西,考慮使用stream.js,它提供了一個「流」數據類型和部分應用的方法。使用stream.js,你的邏輯是這樣的:

// rootStream should be a function which returns a Stream 
// It should construct a stream with the first root produced 
// and a function that returns the remaining roots. 
// Since I don't know how you get your roots, I'll use a stupid example: 
function rootStream() { 
    return new Stream(0, function(){ 
     return new Stream(1); 
    }); 
} 

function isvalid(root) { 
    return root===1; 
} 

Stream.range(0,100) 
.walk(function(v){ 
    //v doesn't seem to be used? 
    var firstvalid = rootStream().filter(isvalid).head(); 
    console.log(firstvalid); 
}); 
相關問題