删除数字数组中的所有重复数字[重复]

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】:

您可以使用closureMap

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?不知道你的意思是什么 例如,如果数组的值9v,那么前面的值为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);

【讨论】:

以上是关于删除数字数组中的所有重复数字[重复]的主要内容,如果未能解决你的问题,请参考以下文章

删除排序数组中的重复数字

删除排序数组中的重复数字

删除排序数组中的重复数字

删除排序数组中的重复数字

删除排序数组中的重复数字

LintCode(100)删除排序数组中的重复数字