删除数字数组中的所有重复数字[重复]
Posted
技术标签:
【中文标题】删除数字数组中的所有重复数字[重复]【英文标题】:Remove all of the duplicate numbers in an array of numbers [duplicate] 【发布时间】:2019-08-10 19:43:54 【问题描述】:我收到这个问题是为了练习,但措辞让我很困惑,因为我看到了它可能想要的 2 个结果。
无论哪种方式,我都希望看到这两种解决方案。
例如,如果我有一个数组:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
我认为这是想要最终结果:
let finalResult = [1, 2, 3, 4, 5, 8, 9, 10];
或者:
let finalResult = [1, 9, 10];
两者之间的区别,一个只是删除所有重复的数字并留下其余部分,第二个只是想要任何不重复的数字。
无论哪种方式,我都想编写两个函数,每个函数都执行一个。
这个,别人给出的,给出了我的第二个解决方案。
let elems = ,
arr2 = arr.filter(function (e)
if (elems[e] === undefined)
elems[e] = true;
return true;
return false;
);
console.log(arr2);
我不确定第一个函数的功能(删除所有重复项)。
【问题讨论】:
如果你使用的是lodash,你可以使用_.uniq()
进一步,这是要求 Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array 的倒数。最后,这篇文章提出了两个不同的问题,并且两者在其他地方已经有了很好的答案。
在评论回答中回答“它是哪一个”的问题:如果您被要求删除重复项,我相信您应该了解第一个变体。第二个变体删除所有 具有 重复项的元素,即“原始”值及其重复项。
【参考方案1】:
使用Set 和Array.from()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
console.log(Array.from(new Set(arr)));
使用正则表达式替换
正则表达式解释here
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = arr
.join(',')
.replace(/(\b,\w+\b)(?=.*\1)/ig, '')
.split(',')
.map(Number);
console.log(res);
交替使用对象
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let obj = arr.reduce((acc, val) => Object.assign(acc,
[val]: val
), );
console.log(Object.values(obj));
【讨论】:
【参考方案2】:只需使用简单的array.filter
单线:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.indexOf(e) == i).sort(function(a, b)return a - b);
console.log(finalResult);
如果您想要第二个结果,可以使用另一个 filter
语句:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.filter(f => f == e).length == 1).sort(function(a, b)return a - b);
console.log(finalResult);
【讨论】:
您还可以添加.sort()
以按数字顺序对它们进行排序:.sort(function(a, b)return a - b)
on finalresult
是的@Mukyuu,那也很有用
值得指出的是,这种方法的运行时间将是输入大小的二次方,除非已知输入数组总是相当小,否则这可能不是很好。
使用多个 array#filter、array#sort 和 array#indexOf 投票最多...这不是高性能
请注意.sort()
不是必要的 - 没有排序的最终结果仍然是一个没有任何重复项的数组,只是与原始数组的顺序相同. (它确实使它与问题中的 finalResult
变量完全匹配。)【参考方案3】:
对于第一部分,您可以使用Set()
和传播语法来删除重复项。
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = [...new Set(arr)]
console.log(res)
第二部分可以使用reduce()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
//to get the object with count of each number in array.
let obj = arr.reduce((ac,a) =>
//check if number doesnot occur before then set its count to 1
if(!ac[a]) ac[a] = 1;
//if number is already in object increase its count
else ac[a]++;
return ac;
,)
//Using reduce on all the keys of object means all numbers.
let res = Object.keys(obj).reduce((ac,a) =>
//check if count of current number 'a' is `1` in the above object then add it into array
if(obj[a] === 1) ac.push(+a)
return ac;
,[])
console.log(res)
【讨论】:
很高兴,第二个看起来很疯狂。我假设与其他结果相比,时间复杂度会不太理想? @mph85 是的,它有点复杂,因为它不会一次又一次地遍历数组,而只是存储所有结果 obj 然后过滤它。它的性能更好 你能提醒我为什么我们需要spread operator
吗?如果我们没有它会发生什么? @Maheer 阿里
是不是因为如果我们没有它,它只会记录一个对象?
@mph85 不,如果我们没有它。我们将有一个Set()
内部数组。我们使用它将Set()
转换为Array
【参考方案4】:
您可以使用closure
和Map
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const build = ar =>
const mapObj = ar.reduce((acc, e) =>
acc.has(e) ? acc.set(e, true) : acc.set(e, false)
return acc
, new Map())
return function(hasDup = true)
if(hasDup) return [...mapObj.keys()]
else return [...mapObj].filter(([key, val]) => !val).map(([k, v])=> k)
const getArr = build(arr)
console.log(getArr())
console.log(getArr(false))
【讨论】:
【参考方案5】:您可以在 One Go 中创建两个数组
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let unique = new Set();
let repeated = Array.from(arr.reduce((acc, curr) =>
acc.has(curr) ? unique.delete(curr) : acc.add(curr) && unique.add(curr);
return acc;
, new Set()));
console.log(Array.from(unique))
console.log(repeated)
【讨论】:
好朋友+1 我想知道三元加&&
是否可能不清楚(x?y:z&&w
)?对我来说,JS 的操作顺序如何处理这一点并不明显,我想知道您是否可以通过使用 if/else
来理解相同的逻辑和推理?【参考方案6】:
您可以使用Array.prototype.reduce() 创建一个hash
对象,其中keys
是数组中的数字,values
将是arr
数组变量中重复出现的数字。
然后使用Object.keys():
删除所有重复的Object.keys(hash)
删除所有重复项,但使用 Array.prototype.filter() 过滤以获取仅出现一次的数字
代码:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const hash = arr.reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), );
// [1, 2, 3, 4, 5, 8, 9, 10];
const finalResultOne = Object.keys(hash);
// [1, 9, 10];
const finalResultTwo = Object.keys(hash).filter(k => hash[k] === 1);
console.log('finalResultOne:', ...finalResultOne);
console.log('finalResultTwo:', ...finalResultTwo);
【讨论】:
【参考方案7】:您可以先对数组进行排序,然后通过仅检查一侧或两侧是否有重复来过滤数组。
var array = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10],
result1,
result2;
array.sort((a, b) => a - b);
result1 = array.filter((v, i, a) => a[i - 1] !== v);
result2 = array.filter((v, i, a) => a[i - 1] !== v && a[i + 1] !== v);
console.log(...result1);
console.log(...result2)
【讨论】:
感谢result1
a[i - 1] !== v
是怎么回事?
a
是数组,i
是实际索引,v
是实际值。它从实际索引之前的索引中获取值,并查看值是否不相等。
啊,好吧,抱歉,它需要value from the index before of the actual index
?不知道你的意思是什么
例如,如果数组的值9
为v
,那么前面的值为8
。
啊好的,谢谢【参考方案8】:
正如许多其他人所说,第一个只是[...new Set(arr)]
对于第二个,只需过滤掉多次出现的那些:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const count = (arr, e) => arr.filter(n => n == e).length
const unique = arr => arr.filter(e => count(arr, e) < 2)
console.log(unique(arr));
【讨论】:
【参考方案9】:var arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
var map = ;
var finalResult = [];
for (var i = 0; i < arr.length; i++)
if (!map.hasOwnProperty(arr[i]))
map[arr[i]] = true;
finalResult.push(arr[i]);
//if you need it sorted otherwise it will be in order
finalResult.sort(function(a, b)
return a - b
);
console.log(finalResult);
【讨论】:
以上是关于删除数字数组中的所有重复数字[重复]的主要内容,如果未能解决你的问题,请参考以下文章