Javascript - 从数组中移除唯一元素

5
我想知道如何从数组中删除独特的元素。例如:var arr = [1, 2, 2, 4, 4]将返回[2, 2, 4, 4]。而[1, 2, 3]将返回[],因为所有元素都是唯一的。我认为需要检查数组中的每个元素与其他元素是否相同,但不确定如何进行操作。
谢谢!

创建一个对象,其键为数组元素,值为元素在数组中出现的次数。从原始数组中删除所有计数为1的元素。 - Barmar
如果你在 Stack Overflow 上搜索,应该能够找到很多解释如何计算重复的问题。 - Barmar
可能是数组中唯一值的重复 - VLAZ
那里最受欢迎的答案(不是被接受的答案)清楚地展示了如何仅获取唯一项。如果你想要将它们“移除”,你只需要简单地反转唯一性检查结果即可。 - VLAZ
还有另一个重复的链接:https://dev59.com/iWox5IYBdhLWcg3waziQ#9229821,还有一个最赞回答不是被采纳的。我认为这个更好,尽管我是在第二次搜索时找到它的。 - VLAZ
嘿,vlaz,我搜索了一段时间,试图找到解决方案。我遇到了你发布的两个解决方案。第一个将数组转换为对象,这是我从未做过的,也不确定如何进行。第二个似乎使用jQuery作为第一个解决方案,然后第二个解决方案是一堆高级JavaScript代码,我甚至不知道从哪里开始。抱歉,我对JavaScript还很新。 - TylerMayfield
9个回答

5
使用ES6,您可以使用Array#map计算值并使用Array#forEach计数。
之后使用Array#filter并检查计数。
如果大于1,返回true(将项目包含在结果集中),否则返回false(不要将项目包含在结果集中)。

function getNotUnique(array) {
    var map = new Map();
    array.forEach(a => map.set(a, (map.get(a) || 0) + 1));
    return array.filter(a => map.get(a) > 1);
}

console.log(getNotUnique([1, 2, 2, 4, 4]));
console.log(getNotUnique([1, 2, 3] ));


1
即使没有ES6,使用“Object”存储计数通常比两个嵌套循环更有效率(在一般情况下)。 - Alnitak
这个完美运行!但是说实话,我真的不太明白为什么。我是一个JavaScript新手! - TylerMayfield
@TylerMayfield 我个人认为你接受了错误的答案。这个问题非常简单 - 它只是构建了一个值->计数的Map,然后取出原始数组中每个计数大于一的值。 - Alnitak
哎呀,我先接受了这个。我以为我可以接受多个。 - TylerMayfield

2
以下是从数组中删除唯一元素的基本且易于理解的方法。

function removeUnique(arr) {
 var newArr = [];
 for (var i = 0; i < arr.length; i++) {
  var count = 0;
  for (var j = 0; j < arr.length; j++) {
   if (arr[j] == arr[i]) {
    count++;
   }
  }
  if (count >= 2) {
   newArr.push(arr[i]);
  }
 }
    return newArr;
}
console.log(removeUnique([1, 2, 2, 4, 4]));


其它答案也可以,但这个是我第一个真正理解的。其它的都在创建对象,而我从未用数组做过这样的操作 :| - TylerMayfield
根据你的问题,我理解你是初学者,因此提供了简单易懂的答案。 - Abhijeet
简单,但非常低效 - 它的时间复杂度是O(n ^ 3) !! - Alnitak
1
我并没有说它很高效,只是很容易理解。 - Abhijeet
两个循环之间的indexOf调用无效 - 括号放错了位置。而且,即使它有效,也会通过使其仅返回原始数组中每个非唯一值的一个条目来破坏代码。这是一个不必要的测试,它使得此代码的时间复杂度为O(n^3),而使用Map可以将其优化到O(n),甚至更低。 - Alnitak
感谢@Alnitak的输入。 - Abhijeet

1
这应该可以做到;

var arr = [1, 2, 2, 4, 4],
    unq = arr.map((e,i,a) => a.filter(f => f === e ).length)
             .reduce((p,c,i) => c === 1 ? p : p.concat(arr[i]) ,[]);
console.log(unq);

然而,仔细考虑后,以下方式可能更易读且更高效。实际上,我们正在利用JS中的一种罕见情况,通过短路运算实现惰性计算。

var r = [1,2,2,4,4].filter((e,i,a) => a.lastIndexOf(e) != i || a.indexOf(e) != i);
console.log(r);

所以a.indexOf(e) != i部分仅对唯一元素和最后遇到的非唯一元素运行。很酷。

1
以下代码返回所有重复的值:
```javascript const getDuplicatedVals = (data) => data.filter((x) => data.indexOf(x) != data.lastIndexOf(x)) ```

0
这里是一个实现(使用https://dev59.com/_G035IYBdhLWcg3wBLTb#5668029)的示例代码。
function removeUnique(arr) {
  var counts = {}

  for(var i = 0; i< arr.length; i++) {
      var num = arr[i]
      counts[num] = counts[num] ? counts[num]+1 : 1
  }

  var result = []
  for(var key in counts) {
    if(Object.prototype.hasOwnProperty.call(counts, key) && counts[key] > 1 {
      result.push(key)
    }
  }

  return result
}


var arr = [1, 2, 3]
var arr2 = [1, 1, 2, 2, 4, 6, 4]

console.log(removeUnique(arr)) // []
console.log(removeUnique(arr2)) // [ '1', '2', '4' ]

0
你可以像这样做(严格使用数组):
var arr = [1,2,3,4,4];
var temp = [];
var to_keep = [];
for(var x = 0; x < arr.length; x++){
  if(temp.indexOf(arr[x]) > -1) {
    if(to_keep.indexOf(arr[x]) == -1)
      to_keep.push(arr[x]);
  } else if(temp.indexOf(arr[x]) == -1) temp.push(arr[x]);
}

for(var y = 0; y < arr.length; y++){
  if(to_keep.indexOf(arr[y]) == -1){
    arr.splice(y,1);
    y--;
  }
}

// arr = [4,4];

0

遍历数组,使用值作为索引进入对象并在原始数据中每次出现时递增。然后遍历对象并提取那些总数大于一的元素。适用于字符串和数字类型。

function dupsOnly(a) {
    var T = {};
    for (var i = 0; i < a.length; i++) {
        if (a[i] in T)
            T[a[i]] += 1;
        else
            T[a[i]] = 1;
    }
    var D = [];
    for (var t in T) {
        if (T[t] > 1)
            D.push(t);
        while (T[t] > 1) {
            T[t] -= 1;
            D.push(t);
       }
    }
    return D;
}

0
var arr = [1, 2, 2, 4, 4]

var dict_with_count = {}
for (var i=0; i<arr.length; i++){
   dict_with_count[arr[i]] = 0
}

for (var i=0; i<arr.length; i++){
   dict_with_count[arr[i]] += 1
}

var new_list = [];

for (key in dict_with_count){
   if (dict_with_count[key] > 1){
       for (var j=0; j<dict_with_count[key]; j++){
          new_list.push(key)
       }
   }
}

console.log(new_list)

0
#include <stdio.h>

int main() {
    int n;

    printf("Enter the length of the array: ");
    scanf("%d", &n);

    int array[n];
    int frequency[1000] = {0}; // Assuming element range from 0 to 999

    printf("Enter the elements of the array:\n");
    for (int i = 0; i < n; i++) {
        scanf("%d", &array[i]);
        frequency[array[i]]++;
    }

    int newSize = 0;

    // Remove unique elements directly in the original array
    for (int i = 0; i < n; i++) {
        if (frequency[array[i]] > 1) {
            array[newSize] = array[i];
            newSize++;
            frequency[array[i]] = 0; // Mark as copied
        }
    }

    printf("Array after deleting unique elements:\n");
    for (int i = 0; i < newSize; i++) {
        printf("%d ", array[i]);
    }

    return 0;
}

你的回答目前写得不清楚。请编辑以添加更多细节,帮助他人理解如何解答问题。你可以在帮助中心找到关于如何撰写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接