簡體   English   中英

刪除數組中的奇數

[英]Remove odd numbers in array

我試圖想出另一種方法來從數組中刪除所有奇數。 一位朋友能夠提出這個解決方案,我理解它的作用,但我沒有找到另一個解決方案。 你對其他解決方案有什么想法嗎?

JavaScript的

let myArray = [1,3,5,7,9,2,4,6,8];
let it = myArray.length;

for(let i=0; i<it; i++) {
  for(let j=0; j<myArray.length; j++ )
    if(myArray[j]%2 === 1){
      myArray.splice(j,1)
      break;
    }
  };

  console.log(myArray);

 let myArray = [1, 3, 5, 7, 9, 2, 4, 6, 8]; myArray = myArray.filter(e => e % 2 === 0) console.log(myArray); 

你的問題是如何“消除賠率”,而不是如何“保持平衡” - 在這種情況下結果是相同的,但你得出答案的方式可能會有所不同。 並不總是一個完全相反的函數直接插入到Array.prototype.filter ,因此這里的所有答案都將在刪除元素的上下文中,我們只能檢測奇數值 - 不保持偶數元素。 我將詳細介紹解決問題的各種方法,但首先讓我們回顧一下您的代碼

你朋友的回答

我在你的內循環上添加了一個console.log ,這樣你就可以看到你正在檢查的每個元素。 很容易看出這個解決方案正在做更多的工作 - 沒有必要創建超過1個循環來迭代你的數字數組。

 let myArray = [1,3,5,7,9,2,4,6,8] let it = myArray.length for(let i = 0; i < it; i++) { for(let j = 0; j < myArray.length; j++ ) { console.log('checking:', myArray[j]) if(myArray[j] % 2 === 1) { myArray.splice(j,1) break } } } console.log(myArray) 

同樣重要的是,當您通過迭代來更改數組的長度時,您需要非常謹慎。 例如,如果你調用arr.splice(i,1) ,那對你的循環有什么影響?

  • “i”右側的所有元素將向左移動1個位置
  • 數組的長度減少1

那么你的循環應該如何適應呢?

  • 如果所有元素在拼接后向左移動,這意味着我們需要再次檢查相同的i ,因為它現在指向一個新值
  • 如果長度減少1,我們需要更改循環退出條件以更快地停止1次迭代

下面的mutRejectOdds答案解決了這些問題


遞歸函數

高度可讀性和直接性,但不是堆棧安全的

 const isOdd = x => x & 1 === 1 const removeOdds = ([x,...xs]) => { if (x === undefined) return [] else if (isOdd(x)) return removeOdds(xs) else return [x, ...removeOdds(xs)] } let data = [1,2,3,4,5,6,7,8] console.log(removeOdds(data)) // [2,4,6,8] console.log(data) // [1,2,3,4,5,6,7,8] 


帶累加器的線性迭代

堆棧安全且非常實用

 const isOdd = x => x & 1 === 1 const removeOdds = xs => { let acc = [] for (let x of xs) if (!isOdd(x)) acc.push(x) return acc } let data = [1,2,3,4,5,6,7,8] console.log(removeOdds(data)) // [2,4,6,8] console.log(data) // [1,2,3,4,5,6,7,8] 


延續傳球風格

大腦扭曲但超級有趣的遞歸解決方案,可以放在蹦床上,使堆棧安全

 const isOdd = x => x & 1 === 1 const identity = x => x const removeOdds = xs => { const aux = ([x,...xs], k) => { if (x === undefined) return k([]) else if (isOdd(x)) return aux(xs, k) else return aux(xs, acc => k([x, ...acc])) } return aux(xs, identity) } let data = [1,2,3,4,5,6,7,8] console.log(removeOdds(data)) // [2,4,6,8] console.log(data) // [1,2,3,4,5,6,7,8] 


高階函數

類似於遞歸函數,但是接受另一個參數,它是要跳過的元素的函數 - 可以用線性迭代樣式或連續傳遞樣式來編寫

 const isOdd = x => x & 1 === 1 const reject = (f, [x,...xs]) => { if (x === undefined) return [] else if (f(x)) return reject(f, xs) else return [x, ...reject(f, xs)] } let data = [1,2,3,4,5,6,7,8] console.log(reject(isOdd, data)) // [2,4,6,8] console.log(data) // [1,2,3,4,5,6,7,8] 


函數組合與Array.prototype.filter

使用非常實用的內置Array.prototype.filter但返回使用函數組合物與相反的結果not

 const isOdd = x => x & 1 === 1 const comp = f => g => x => f(g(x)) const not = x => !x const reject = (f, xs) => xs.filter(comp(not)(f)) let data = [1,2,3,4,5,6,7,8] console.log(reject(isOdd, data)) // [2,4,6,8] console.log(data) // [1,2,3,4,5,6,7,8] 


具有就地變異的線性迭代

我上面實現的所有方法都不會改變原始data - 在某些情況下,如果你有一個特別大的數組並且你不想創建一個刪除了奇數值的副本 ,你可能希望執行data的就地修改

此答案解決了原始代碼中的問題

 const isOdd = x => x & 1 === 1 const mutRejectOdds = xs => { for (let i = 0, len = xs.length; i < len; i++) if (isOdd(xs[i])) (xs.splice(i,1), i--, len--) } let data = [1,2,3,4,5,6,7,8] console.log(mutRejectOdds(data)) // undefined console.log(data) // [2,4,6,8] 

如果您只需要支持IE9,您可以使用Array.prototype.filter方法。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var output = arr.filter(function(item) {
    return item % 2 === 0;
});

輸出將是過濾值的新數組(僅偶數)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM