2014-02-18 48 views
0

我正在嘗試編寫一個reduce函數,它爲數組中的每個新唯一值分配一個增量整數,並構建一個將唯一元素映射到增量索引的字典。在減少函數內保留一個計數器

我的期望的功能消耗這樣的數組:

[3,1,1,2,3,1,5,1,2] 

並輸出一個地圖,看起來像這樣:

功能看起來像這樣:

{3: 0, 1: 1, 2: 2, 5: 3} 

一個潛在的解決方案是使用減少,但它需要保持櫃檯外的功能:

var i = 0 
var func = [3,1,1,2,3,1,5,1,2].reduce(function(a, b) { 
    if (!(a in b) { 
    b[a] = i 
    i++ 
    } 
    return b 
},{}) 

有沒有辦法寫這個函數,但不知何故保持計數器在函數的範圍內?很明顯,我可以將所有內容都包含在一個函數中,但有沒有辦法通過簡化來實現?

+0

@RobertRozas:那不行。 '我'將永遠是0. – Chuck

回答

3

使用關閉將有助於保持你的代碼簡潔:

fun=function(){ 
var i=0; 
return function(b, a) { 
    if (!(a in b)) { 
    b[a] = i 
    i++ 
    } 
    return b; 
}; 
}(); 

var func = [3,1,1,2,3,1,5,1,2].reduce(fun,{}) 

所以,你必須fun同時降低。

2

Array.prototype.reduce takes 4 arguments.您可能會考慮使用它們,因爲它們中的一個是索引值。因此,不需要櫃檯。

var func = [3,1,1,2,3,1,5,1,2].reduce(function(prev, curr, idx, arr) { 
    if(!(prev in curr)) curr[prev] = (prev.length > 0) ? prev.length - 1 : 0; 
    return curr; 
}); 
+0

但他並不嚴格尋找索引;他實際上需要一個*計數器*(請參閱示例代碼在每次調用時不會增加「i」,僅當遇到唯一值時)。 –

+0

我意識到索引可能不是您需要的值,但是由於原始數組作爲第四個參數傳入,因此您可以使用它獲取要查找的位置的值的第一個索引,而不是使用增量變量。 – pwnyexpress

0

你可以總是拋出i到對象本身:

[3,1,1,2,3,1,5,1,2].reduce(function(a,b) { 
    if(a[b]===undefined) a[b] = a.i++; return a},{i:0}) 

// {1: 1, 2: 2, 3: 0, 5: 3, i: 4} 
0

答案是肯定的,但它可能比只用一個範圍功能更加尷尬。基本上,您只需將您的狀態值設置爲您想要的實際結果和附加狀態的組合,然後在完成縮減時提取結果。

var func = [3,1,1,2,3,1,5,1,2].reduce(function(memo, val) { 
    if (!(val in memo[0])) { 
    memo[0][val] = memo[1] 
    memo[1]++ 
    } 
    return memo 
}, [{}, 0])[0]