简体   繁体   English

JavaScript:在reduce方法(折叠)中引用剩余的Array?

[英]JavaScript: Refer to remaining Array in the reduce method (fold)?

I want to test wether an Array consists only of unique elements and my solution is the following: 我想测试一个仅包含唯一元素的数组,而我的解决方案如下:

function uniqueElements(a) {
  var r = true;
  while (a) {
    var [el, a] = [a.slice(0,1), a.slice(1)];
    r &= !a.includes(el);
  };
  return !!r;
}

This method works. 此方法有效。 However, since I am adopting a more functional style, and because folds are awesome, I would like to implement a function which looks somewhat like this: 但是,由于我采用的是一种更具功能性的样式,并且因为折叠很棒,所以我想实现一个看起来像这样的函数:

function uniqueElements(a) {
  var isUnique = (acc, el) => acc &= !remainingArray.includes(el);
  return a.reduce(isUnique, true);
}

I can't figure out how to get to that remainingArray variable. 我不知道如何获得该remainingArray数组变量。 Does anybody know how to get it? 有人知道如何获得吗? Is this even possible in JS, and if not, how could that function be expressed through a fold? 在JS中甚至可以做到这一点,如果不能,那么该函数如何通过折叠来表示?

Remember not to get stuck in a pattern of thinking. 记住不要陷入思维模式。 Folds are great but in JavaScript there's no way to stop folding early if our result can be computed before traversing the entire array 折叠很棒,但是在JavaScript中,如果可以在遍历整个数组之前计算出结果,就无法尽早停止折叠

In other words, what is the answer of the following? 换句话说,以下答案是什么? true or false ? true还是false

uniqueElements ( [ 1 , 1 , 2 , 3 , ... thousands more items ] )
// => true or false ?

We can determine the answer to be false immediately after processing the second 1 . 处理完第二个1后,我们可以立即确定答案为false There's no need to keeping folding in 2 , or 3 , or the rest of the array as they will not affect the false outcome 无需保持折叠成23或数组的其余部分,因为它们不会影响false结果

A possible solution is a simple recursive procedure 可能的解决方案是简单的递归过程

 const isUnique = ([ x, ... xs ], set = new Set ()) => x === undefined ? true : set.has (x) ? false // we already found a non-unique, stop recurring : isUnique (xs, set.add (x)) console.log (isUnique ([])) // true console.log (isUnique ([ 1, 2, 3 ])) // true console.log (isUnique ([ 1, 1, 2, 3 ])) // false 

Or a stack-safe solution that still maintains a pure functional interface – if I had to guess, this is probably 10x faster than the above program and doesn't expose private API 还是仍然保持纯功能接口的堆栈安全解决方案–如果我不得不猜测,这可能比上述程序快10倍,并且不会公开私有API

 const isUnique = xs => { const set = new Set () for (const x of xs) if (set.has (x)) return false else set.add (x) return true } console.log (isUnique ([])) // true console.log (isUnique ([ 1, 2, 3 ])) // true console.log (isUnique ([ 1, 1, 2, 3 ])) // false 

Or make up your own solution – either way, just don't get cornered into thinking folds need to be used wherever your touch a traversable data structure. 或自行制定解决方案–无论哪种方式,只要您不介意只要您触摸可遍历的数据结构,就需要使用折叠。

And in a more general sense, you need to practice imagining what the process of your function looks like. 从更一般的意义上讲,您需要练习想象一下函数的过程。 I recommend that you play compiler/evaluator with a pencil and paper while you're first getting the hang of it. 我建议您在第一次使用时要用铅笔和纸玩编译器/评估器。 Eventually you will be able to envision simple processes in your head; 最终,您将可以想到简单的过程; and then more complex ones with practice over time – I say this because you probably wouldn't have reached for a fold to complete this task if you could see how silly it looks to continue folding after the result can be returned 然后是更复杂的练习-随着时间的推移,我会这样说,因为如果您可以看到返回结果继续折叠看起来多么愚蠢,那么您可能就不会折叠完成该任务

On that note, that is why I used Set to check for uniques as opposed to .includes . 关于这一点,这就是为什么我使用Set来检查唯一性而不是.includes Sets can do binary search whereas array searches are linear – looking for your item in an array one-by-one just seems silly once you can see what that process would look like for a significantly large input. 集合可以执行二进制搜索,而数组搜索则是线性的–一旦您看到输入非常大的过程看起来像什么,就一个接一个地在数组中查找项目似乎很愚蠢。 Only when you're envisioning process can you see how alternative data structures like Set can dramatically lower the time complexity of your function 只有在构想过程时,您才能看到Set等替代数据结构如何显着降低函数的时间复杂度

You could slice the array: 您可以切片数组:

function isUnique(xs) {
  return xs.reduce((acc, x, i) => {
    if (xs.slice(i + 1).includes(x)) {
      return false;
    }
    return acc;
  }, true);
}

Although, as mentioned in the comments, you could also use a hash for better performance if you have strings or numbers in your array. 尽管如评论中所述,但是如果数组中有字符串或数字,也可以使用哈希来提高性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM