繁体   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