javascript - 如何通过递归将重复的字符串/数字推送到 newArr?
问题描述
如何使用递归检查数组中的重复数字/字符串,然后将它们推送到 newArr 中,并将唯一的数字/字符串推送到 newArrTwo
function rec(those) {
let [unique, twin] = [ [], [] ];
};
console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));
我想要的输出是unique = ["arr", "obj", "arg"];
和 twin = [2,"str"]
解决方案
更新
我最初误读了规格。在本节下面,我详细介绍了针对不同但相关问题的几种解决方案。这是请求的解决方案:
const rec = (arr, uniqs = new Set, dups = new Set, [x, ...xs] = arr) =>
arr.length == 0
? [[...uniqs], [...dups]]
: uniqs.has(x) || dups.has(x)
? rec(xs, (uniqs.delete(x), uniqs), dups.add(x))
: rec(xs, uniqs.add(x), dups)
console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));
请注意,最终原始答案有两个变化:
我们也切换到了 Set
dups
,并进行了所需的更改。此行现在从
uniqs
Set 中删除,而不仅仅是传递它:? rec(xs, (uniqs.delete(x), uniqs), dups.add(x))
这实际上指向了一个 API 问题Set
。add
返回集合真的很有用。delete
不这样做也太糟糕了。虽然布尔返回有时可能会有所帮助,但使用has
. 解决这个问题为时已晚,但这确实是一种耻辱。
原始答案
这是一种可能的方法。ES6 的特性,例如休息参数和默认参数,以及Symbol
一个相当优雅的实现。
const None = Symbol()
const rec = ([x = None, ...xs], uniqs = [], dups = []) =>
x == None
? [uniqs, dups]
: uniqs.includes(x)
? rec(xs, uniqs, dups.concat(x))
: rec(xs, uniqs.concat(x), dups)
console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));
现代 JS 中递归的一个真正帮助是能够使用默认参数来避免额外的辅助函数。
使用Symbol
here 是一种有趣的方式,可以将输入数组的展开组合成一个头部和一个尾部,并且仍然允许我们测试它是否为空。另一种方法如下所示。
const rec = (arr, uniqs = [], dups = [], [x, ...xs] = arr) =>
arr.length == 0
? [uniqs, dups]
: uniqs.includes(x)
? rec(xs, uniqs, dups.concat(x))
: rec(xs, uniqs.concat(x), dups)
console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));
这个版本感觉比原来的干净一些,但它不需要定义一个辅助符号来检查是否有空。
这仍然有问题;它可能有性能问题。因为我们必须O(n)
includes
为每个元素调用 ,所以整个解决方案类似于O(n^2)
,取决于唯一值与重复值的比率。这可能不是问题,我只会在以下两种情况之一中修复它:
- 我已经测试并发现此代码是我的应用程序中的实际瓶颈
- 我有一个性能更高的替代版本,它几乎不牺牲代码清晰度。
在这种情况下,我确实有这样一个版本:
const rec = (arr, uniqs = new Set(), dups = [], [x, ...xs] = arr) =>
arr.length == 0
? [[...uniqs], dups]
: uniqs.has(x)
? rec(xs, uniqs, dups.concat(x))
: rec(xs, uniqs.add(x), dups)
console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));
(我们也可以Symbol
在这个版本中使用替代方案。)
在这里,我们切换到使用 a Set
,这正是为处理独特元素集合而设计的数据类型。这需要对集合进行一些解包,[...uniqs]
或者Array.from(uniqs)
- 但这只是复杂性的非常小的增加。其他更改只是与从数组切换到集合有关。
推荐阅读
- java - getRowIndex 总是返回 null
- javascript - 使用 Knex js 修改列的大小
- image - 如何在 Xamarin Forms 中合并两个图像?
- node.js - 如何在 Express 中将 JSON 描述符附加到 res.sendFile()?
- python - 访问列表中的项目并形成图表
- listview - 我怎样才能让它在颤动中滚动
- c++ - 如何向 Qt Creator 添加新工具包
- laravel - Eloquent SELECT "string" AS content_type 导致错误
- php - php中的支付api多维数组问题
- powershell - 正则表达式匹配上的Powershell替换字符串