簡體   English   中英

比較2個數組並使用Ramda找到相等的值

[英]Comparing 2 arrays and finding equal values with Ramda

我最近愛上了函數編程,並開始學習ramda.js,但是我似乎還無法進入函數思維方式。 我有2個字符串數組(它們實際上是分割后的字符串),我想找出第一個字符串中的多少個字符等於第二個字符串中相同位置的那些字符。 迫切需要按照以下方式做一些非常簡單的事情:

let counter = 0
for(let i = 0; i < array.length; i++){
  if(firstArray[i] === secondArray[i]) counter++
}

但是我怎么用ramda呢?

“ ...使用rambda”

這是您可以做到的一種方法-還有無數其他方法...

const countEqualChars = (a, b) =>
  R.sum(R.zipWith(R.equals, a, b))

countEqualChars(
  [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ],
  [ 'a', 'b', 'c', 'x', 'y', 'z', 'g' ]
)
// 4

countEqualChars('abcdefg', 'abcxyzg')
// 4

但是...

這基本上是您進行函數式編程的錯誤方法。 忘記Rambda,直到您對如何以功能性方式推理程序有了很好的認識。 如果您不知道事情在根本上是如何工作的,您將永遠無法欣賞Rambda的便利。

從了解遞歸作為for/while循環的替代方法開始。 循環沒有什么問題,但是遞歸有時會允許您以更好的方式表達事物……

 const a = 'abcdefg' const b = 'abcxyzg' const countEqualChars = ([ x, ...xs ], [ y, ...ys ]) => { if (x === undefined || y === undefined) return 0 else if (x === y) return 1 + countEqualChars (xs, ys) else return countEqualChars (xs, ys) } console.log (countEqualChars (a, b)) // 4 

現在,我們看到此功能做了很多工作。 我們一次檢查一個元素的數組,進行比較和計數。 也許我們可以將其分解為一些單獨的任務,以使我們的功能隨着時間的推移更加可維護。 讓我們從一個允許我們配對兩個數組的相等索引的函數開始...

 const zip = ([ x, ...xs ], [ y, ...ys ]) => x === undefined && y === undefined ? [] : [ [ x, y ], ...zip (xs, ys) ] console.log (zip ([ 1, 2, 3 ], [ 'a', 'b', 'c' ])) // [ [ 1, 'a' ] // , [ 2, 'b' ] // , [ 3, 'c' ] // ] 

接下來,我們可以使用內置的filter函數創建一個僅包含我們想要的東西的新數組

 const xs = [ 1, 1, 2, 2, 3, 3, 4, 4 ] const justThrees = xs.filter (x => x === 3) console.log (justThrees) // [ 3, 3 ] 

結合這些zipfilter層,我們可以從字符串中配對每個索引,然后刪除不匹配的對...

 const zip = ([ x, ...xs ], [ y, ...ys ]) => x === undefined && y === undefined ? [] : [ [ x, y ], ...zip (xs, ys) ] const eq = (x, y) => x === y const apply = f => xs => f (...xs) const a = 'abcdefg' const b = 'abcxyzgh' const matches = zip (a, b) .filter (apply (eq)) console.log (matches) // [ [ 'a', 'a' ] // , [ 'b', 'b' ] // , [ 'c', 'c' ] // , [ 'g', 'g' ] // ] 

現在剩下的就是計算匹配對。 我們也將整個事情變成一個函數,以便您可以根據需要重新使用它

 const zip = ([ x, ...xs ], [ y, ...ys ]) => x === undefined && y === undefined ? [] : [ [ x, y ], ...zip (xs, ys) ] const eq = (x, y) => x === y const apply = f => xs => f (...xs) const countEqualChars = (a, b) => zip (a, b) .filter (apply (eq)) .length console.log (countEqualChars ('abcdefg', 'abcxyzgh')) // 4 

最重要的是 ...

您會看到,我們手工得出的解決方案與Rambda所使用的解決方案略有不同 那是因為編程並不是魔術,在意識到其他工具甚至不知道它們在做什么之前,您將發明許多自己的工具。

有數百種方法可以解決我剛剛遇到的問題,並且我在做出的每個選擇中都需要權衡取舍。 您的總體目標是能夠將您的程序分解為各個組成部分,並隨着時間的流逝而學習取舍。

將其與試圖理解為什么某個函數存在於某個庫中只是為了讓您可以猜測要在哪里使用它進行比較……通過這樣做,您將擅長進行函數式編程,而無需復制/粘貼人們聰明的Rambda單行代碼。 一旦了解了為什么 equalszipWithsum存在,就知道何時使用它們。

我無法與其他出色的答案競爭,但不要忘記array原型具有許多有用的方法,例如filterreduce

 var countMatches = (a, b) => a.reduce((sum, c, i) => b[i] === c ? ++sum : sum , 0); var set1 = "1234678".split(""); var set2 = "1234568".split(""); console.log(countMatches(set1, set2)); 

如果您只是想看看兩個數組有什么共同點,可能想看看交集

R.intersection([1,2,3,4], [7,6,5,4,3]); //=> [4, 3]

暫無
暫無

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

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