Nhận tất cả các giá trị không duy nhất (nghĩa là: trùng lặp / nhiều lần xuất hiện) trong một mảng


418

Tôi cần kiểm tra một mảng JavaScript để xem liệu có bất kỳ giá trị trùng lặp nào không. Cách dễ nhất để làm điều này là gì? Tôi chỉ cần tìm các giá trị trùng lặp là gì - tôi thực sự không cần chỉ mục của chúng hoặc số lần chúng được nhân đôi.

Tôi biết tôi có thể lặp qua mảng và kiểm tra tất cả các giá trị khác cho một trận đấu, nhưng có vẻ như nên có một cách dễ dàng hơn.

Câu hỏi tương tự:


22
Dường như có nhiều năm nhầm lẫn về những gì câu hỏi này yêu cầu. Tôi cần biết những phần tử nào trong mảng được sao chép: "Tôi chỉ cần tìm những giá trị trùng lặp là gì". Câu trả lời đúng KHÔNG nên loại bỏ trùng lặp khỏi mảng. Đó là nghịch đảo của những gì tôi muốn: một danh sách các bản sao, không phải là danh sách các yếu tố độc đáo.
Scott Saunders

Câu trả lời:


301

Bạn có thể sắp xếp mảng và sau đó chạy qua nó và sau đó xem liệu chỉ mục tiếp theo (hoặc trước đó) có giống với hiện tại không. Giả sử thuật toán sắp xếp của bạn là tốt, giá trị này sẽ nhỏ hơn O (n 2 ):

const findDuplicates = (arr) => {
  let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
  // JS by default uses a crappy string compare.
  // (we use slice to clone the array so the
  // original array won't be modified)
  let results = [];
  for (let i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
      results.push(sorted_arr[i]);
    }
  }
  return results;
}

let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

Trong trường hợp, nếu bạn trở lại là một hàm cho các bản sao. Đây là loại trường hợp tương tự.

Tham khảo: https://stackoverflow.com/a/57532964/8119511


10
"Giả sử thuật toán sắp xếp của bạn là tốt, thì thuật toán này phải nhỏ hơn O ^ 2". Cụ thể, nó có thể là O (n * log (n)).
ESRogs

83
Kịch bản này không làm việc rất tốt với hơn 2 bản sao (ví dụarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie

7
@swilliams Tôi không nghĩ những hướng dẫn đó nói bất cứ điều gì về việc không sử dụng i++. Thay vào đó, họ nói không viết j = i + +j. Hai điều khác nhau IMHO. Tôi nghĩ i += 1là khó hiểu hơn đơn giản và đẹp i++:)
Danilo Bargen

34
-1 Câu trả lời này sai ở nhiều cấp độ. Trước hết var sorted_arr = arr.sort()là vô dụng: làm arr.sort()biến đổi mảng ban đầu (vốn là một vấn đề theo đúng nghĩa của nó). Điều này cũng loại bỏ một yếu tố. (Chạy mã ở trên. Điều gì xảy ra với 9?) Cc @dystroy Một giải pháp sạch hơn sẽ làresults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException

24
Mọi người: câu hỏi yêu cầu hiển thị các giá trị trùng lặp, không xóa chúng. Vui lòng không chỉnh sửa / phá mã để cố làm cho nó làm điều gì đó mà nó không cố gắng thực hiện. Cảnh báo sẽ hiển thị các giá trị được nhân đôi.
Scott Saunders

205

Nếu bạn muốn tách ra các bản sao, hãy thử giải pháp tuyệt vời này:

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

Nguồn: http://dreaminginjavascript.wordpress.com/2008/08/22/006inating-d repeatates /


18
Đó là mã tốt, nhưng thật không may, nó không làm những gì tôi yêu cầu.
Scott Saunders

67
Đoạn mã trên (là của tôi - đó là blog của tôi) giúp bạn khá gần gũi. Một tinh chỉnh nhỏ và bạn đang ở đó. Trước hết, bạn có thể xem nếu Array.length và out.length giống nhau. Nếu chúng giống nhau, không có yếu tố trùng lặp. Nhưng bạn muốn nhiều hơn một chút. Nếu bạn muốn "bắt" các bản sao khi chúng xảy ra, hãy kiểm tra xem liệu độ dài của mảng có tăng sau dòng obj [Array [i]] = 0 không. Tiện lợi hả? :-) Cảm ơn những lời tốt đẹp, Raphael Montanaro.
Nosredna

6
@MarcoDemaio: Uh, không, tại sao mã không hoạt động với dấu cách? Bạn có thể đặt bất cứ thứ gì bạn thích vào một tên thuộc tính - chỉ không thể sử dụng cú pháp dấu chấm để truy cập vào các khoảng trắng (cũng như các đạo cụ với nhiều ký tự khác sẽ phá vỡ phân tích cú pháp).
Gijs

4
@Gijs: +1 bạn đúng. Tôi không biết điều đó. Nhưng nó vẫn không hoạt động khi đó là một mảng các đối tượng.
Marco Demaio

3
Thuật toán này cũng có tác dụng phụ là trả về một mảng đã sắp xếp, có thể không phải là điều bạn muốn.
bất đối xứng

165

Đây là câu trả lời của tôi từ chuỗi trùng lặp (!):

Khi viết mục này 2014 - tất cả các ví dụ là vòng lặp for hoặc jQuery. Javascript có các công cụ hoàn hảo cho việc này: sắp xếp, ánh xạ và thu nhỏ.

Tìm các mục trùng lặp

var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

var uniq = names
  .map((name) => {
    return {
      count: 1,
      name: name
    }
  })
  .reduce((a, b) => {
    a[b.name] = (a[b.name] || 0) + b.count
    return a
  }, {})

var duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)

console.log(duplicates) // [ 'Nancy' ]

Cú pháp chức năng khác:

@ Dmytro-Laptin đã chỉ ra một số mã mã bị xóa. Đây là một phiên bản nhỏ gọn hơn của cùng một mã. Sử dụng một số thủ thuật ES6 và các hàm bậc cao hơn:

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const count = names =>
  names.reduce((a, b) => ({ ...a,
    [b]: (a[b] || 0) + 1
  }), {}) // don't forget to initialize the accumulator

const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1)

console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))) // [ 'Nancy' ]


1
Đây là loại giải pháp tôi đang tìm kiếm. Nếu tôi muốn có một tá vòng lặp, điều đó khá dễ viết. Từ khóa trong OP là "hiệu quả".
Josh

@ChristianLandgren, biến 'dict' được khai báo ở đâu? có lẽ 'đếm' nên được sử dụng thay thế?
Dmytro Laptin

4
Hãy giữ ý kiến ​​sai lệch của bạn cho chính mình (-1 vì kiêu ngạo). Cá nhân tôi cảm thấy mệt mỏi với những người khó hiểu "ngắn" và "hiệu quả", và đăng một bài lót mà không đặt câu hỏi về màn trình diễn. Các chương trình ngắn và JS hiện đại KHÔNG tốt hơn về bản chất. Lạm dụng điển hình của từ "hiệu quả" ở đây . Niềm tin ngây thơ điển hình ở đây (đọc bình luận sau). Demo tại đây .

1
@leaf - vui lòng giữ lời đề nghị của bạn cho câu trả lời của riêng bạn. Giải pháp bạn chỉnh sửa là không thể đọc được, nó có thể là hiệu suất (có thể không) nhưng ngay cả như vậy - khả năng đọc thường quan trọng hơn hiệu suất theo quan điểm của tôi. Nhưng quan trọng nhất - không xóa mã của người khác để thay thế mã của bạn mà không có lý do.
Christian Landgren

1
Câu trả lời khác nhau, vâng, ý kiến ​​khác nhau, tôi không nghĩ vậy.

64

Tìm các giá trị trùng lặp trong một mảng

Đây phải là một trong những cách ngắn nhất để thực sự tìm thấy các giá trị trùng lặp trong một mảng. Như OP yêu cầu cụ thể, điều này không loại bỏ trùng lặp mà tìm thấy chúng .

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

Điều này không cần sắp xếp hoặc bất kỳ khuôn khổ bên thứ ba. Nó cũng không cần vòng lặp thủ công. Nó hoạt động với mọi giá trị indexOf () (hoặc rõ ràng hơn: toán tử so sánh nghiêm ngặt ) hỗ trợ.

Do giảm ()indexOf (), nó cần ít nhất IE 9.


7
Mũi tên ES6 / phiên bản đơn giản / thuần túy:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies

30

Bạn có thể thêm chức năng này hoặc điều chỉnh nó và thêm nó vào nguyên mẫu Array của Javascript:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);

Đây là giải pháp tốt nhất, nhưng hãy cẩn thận khi thêm nó vào nguyên mẫu mảng, vì điều đó sẽ làm rối tung IE nếu lặp qua các giá trị.
Sampsa Suoninen

@RoyTinker perl cũng hỗ trợ họ, nhưng tôi không biết javascript đã làm gì
Luke H

1
Không làm những gì OP yêu cầu, trả lại các bản sao.
RWC

27

CẬP NHẬT: Sau đây sử dụng một chiến lược kết hợp tối ưu hóa. Nó tối ưu hóa tra cứu nguyên thủy để hưởng lợi từ thời gian tra cứu băm O (1) (chạy uniquetrên một mảng nguyên thủy là O (n)). Tra cứu đối tượng được tối ưu hóa bằng cách gắn thẻ các đối tượng với một id duy nhất trong khi lặp qua để xác định các đối tượng trùng lặp cũng là O (1) cho mỗi mục và O (n) cho toàn bộ danh sách. Ngoại lệ duy nhất là các mặt hàng bị đóng băng, nhưng những thứ đó rất hiếm và dự phòng được cung cấp bằng cách sử dụng một mảng và indexOf.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

Nếu bạn có Bộ sưu tập ES6, thì có một phiên bản đơn giản hơn và nhanh hơn đáng kể. (shim cho IE9 + và các trình duyệt khác tại đây: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}

có thật không? Tại sao trả lời một câu hỏi đã được giải quyết hơn 2 năm trước?
Rene Pot

3
Tôi đang trả lời một câu hỏi khác và dường như vô tình nhấp vào ai đó liên kết với câu hỏi này, gọi nó là một bản sao, và cuối cùng nhân bản câu trả lời của tôi và làm tôi bối rối. Tôi chỉnh sửa công cụ của tôi rất nhiều.


16
Tôi nghĩ nó tốt với các giải pháp khác nhau. Không có vấn đề gì khi chủ đề đã cũ và được giải quyết vì vẫn có thể đưa ra những cách khác nhau để làm điều này. Đó là một vấn đề điển hình trong khoa học máy tính.
Emil Vikström

Bạn có thể muốn đề cập rằng điều này phụ thuộc vào các phương thức ES5 Array không được triển khai trong IE <9
Tim Down

24

CẬP NHẬT: Một lớp lót ngắn để có được các bản sao:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

Để có được mảng mà không trùng lặp, chỉ cần đảo ngược điều kiện:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

Tôi chỉ đơn giản là không nghĩ về filter()câu trả lời cũ của tôi dưới đây;)


Khi tất cả những gì bạn cần là kiểm tra xem không có bản sao nào được hỏi trong câu hỏi này, bạn có thể sử dụng every()phương thức:

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

Lưu ý rằng every()không hoạt động cho IE 8 trở xuống.


1
Không làm những gì OP yêu cầu, trả lại các bản sao.
RWC

Đúng, tôi đã cập nhật câu trả lời của mình để khắc phục điều đó.
Laurent Payot

Giải pháp hoàng gia! thnaks
Jeremy Piednoel

21
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})

Điều này có vẻ hiệu quả, nhưng có lẽ bạn nên bao gồm một số văn bản mô tả cách thức hoạt động của nó.
Máy cắt DIMM

1
Sẽ không hoạt động nếu có nhiều hơn 2 lần xuất hiện của một giá trị trùng lặp.
vasa

1
Đây là thanh lịch và đơn giản. Tôi thích nó. Đối với những người muốn tìm hiểu cách họ làm việc, tôi đã tạo ra một ý chính cho thấy cách hiển thị các bản sao và loại bỏ các bản sao. Xem tại đây: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Josh

@TheDIMMReaper cho 'a'mảng thứ hai , bên trong bộ lọc có chức năng index == 1, trong khi đóself.indexOf('a') == 0
Sergiy Ostrovsky

19

Điều này sẽ giúp bạn có được những gì bạn muốn, Chỉ là các bản sao.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.

13

sử dụng underscore.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}

9

ES2015

//          🚩🚩   🚩                 🚩 
var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique;

// Combine all the arrays to a single one
unique = arr.concat(arr2, arr3)

// create a new (dirty) Array with only the unique items
unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' )

// Cleanup - remove duplicate & empty items items 
unique = [...new Set(unique)].filter(n => n)

console.log(unique)


Tìm các giá trị duy nhất từ ​​3 mảng (hoặc nhiều hơn):

Array.prototype.unique = function () {
    var arr = this.sort(), i; // input must be sorted for this to work
    for( i=arr.length; i--; )
      arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item

    return arr;
}

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,9],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    // merge arrays & call custom Array Prototype - "unique"
    unique = arr.concat(arr2, arr3).unique();

console.log(unique);  // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4]

Chỉ là một polyfill cho mảng indexOf cho các trình duyệt cũ:

if (!Array.prototype.indexOf){
   Array.prototype.indexOf = function(elt /*, from*/){
     var len = this.length >>> 0;

     var from = Number(arguments[1]) || 0;
     from = (from < 0) ? Math.ceil(from) : Math.floor(from);
     if (from < 0)
        from += len;

     for (; from < len; from++){
        if (from in this && this[from] === elt)
           return from;
     }
     return -1;
  };
}

Giải pháp jQuery sử dụng "inArray":

if( $.inArray(this[i], arr) == -1 )

thay vì thêm Array.prototype.indexOf


+1 vì mã chắc chắn dễ đọc hơn khi sử dụng Array.indexOf, nhưng thật không may, nó có vẻ chậm hơn so với sử dụng một vòng lặp lồng đơn giản. Ngay cả trên các trình duyệt thực hiện Array.indexOf ngày nay giống như FF. Xin vui lòng, hãy xem các thử nghiệm này tôi đã làm ở đây: jsperf.com/array-unique2 và cho tôi biết suy nghĩ của bạn.
Marco Demaio

@shekhardesigner - câu trả lời cập nhật. "r" là mảng bạn tìm kiếm trong
vsync

@vsync Tôi phải khởi tạo, var r = [];để mã của bạn hoạt động. Và làm việc như quyến rũ.
Shekhar K. Sharma

@shekhardesigner - Tôi xin lỗi vì sự pha trộn, đối với giải pháp Array Prototype bạn không cần một rbiến
vsync

2
Không làm những gì OP yêu cầu, trả lại các bản sao.
RWC

8

Đây là giải pháp đơn giản và một dòng của tôi.

Nó tìm kiếm các phần tử duy nhất trước tiên, sau đó làm cho mảng tìm thấy là duy nhất với việc sử dụng Set.

Vì vậy, chúng tôi có mảng trùng lặp cuối cùng.

var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];

console.log([...new Set(
  array.filter((value, index, self) => self.indexOf(value) !== index))]
);


7

Đây là đề xuất của tôi (ES6):

let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]

// b is now [1, 2, 4]

1
Điều này sẽ báo cáo rằng một lần xuất hiện undefinedlà trùng lặp.
Dem Pilafian

1
@DemPilafian cảm ơn bạn, đã cập nhật
lukaszkups

6
var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});

hoặc khi được thêm vào prototyp.chain of Array

//copy and paste: without error handling
Array.prototype.unique = 
   function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}

Xem tại đây: https://gist.github.com/1305056


1
Hàm bộ lọc sẽ trả về true hoặc false, không phải chính phần tử. Lọc một mảng chứa 0's sẽ không trả về chúng.
mflodin

Ngoài ra, tôi giả sử i&&là để tránh đi ra khỏi giới hạn của mảng, nhưng điều đó cũng có nghĩa là phần tử đầu tiên trong mảng được sắp xếp sẽ không được đưa vào. Trong ví dụ của bạn không có 1trong mảng kết quả. Tức return i&&v!==o[i-1]?v:0;return v!==o[i-1];
mflodin

6

Cách nhanh chóng và thanh lịch bằng cách sử dụng phá hủy và giảm đối tượng es6

Nó chạy trong O (n) (1 lần lặp trên mảng) và không lặp lại các giá trị xuất hiện hơn 2 lần

const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
  dup
} = arr.reduce(
  (acc, curr) => {
    acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
    if (acc.items[curr] === 2) acc.dup.push(curr)
    return acc
  }, {
    items: {},
    dup: []
  },
)

console.log(dup)
// ['hi', 'bye']


5

Đây là giải pháp đơn giản nhất tôi có thể nghĩ ra:

    const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']

    const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
    // => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]

    const duplicates = [...new Set(filtered)]

    console.log(duplicates)
    // => [ 2, 0, -1, 'a' ]

Đó là nó.

Ghi chú:

  1. Nó hoạt động với bất kỳ số bao gồm 0, chuỗi và số âm ví dụ -1- câu hỏi liên quan: Nhận tất cả các giá trị duy nhất trong một mảng JavaScript (bản sao remove)

  2. Mảng ban đầu arrđược bảo tồn ( filtertrả về mảng mới thay vì sửa đổi bản gốc)

  3. Các filteredmảng chứa tất cả các bản sao; nó cũng có thể chứa nhiều hơn 1 giá trị giống nhau (ví dụ: mảng được lọc của chúng tôi ở đây là [ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. Nếu bạn muốn nhận được chỉ giá trị được nhân đôi (bạn không muốn có nhiều trùng lặp có giá trị như nhau), bạn có thể sử dụng [...new Set(filtered)](ES6 có một đối tượng Set mà có thể lưu trữ các giá trị chỉ duy nhất)

Hi vọng điêu nay co ich.


5

JS vanilla ngắn nhất :

[1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]

4

Đây là một cách rất nhẹ nhàng và dễ dàng:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}

Câu trả lời tốt nhất. Và nếu người dùng muốn mảng phần tử trùng lặp, vì điều này tôi đã cập nhật mã @brandon var i = mã .length; var trùng lặp = []; while (i--) {if (mã .indexOf (mã [i])! = i) {if (trùng lặp ; } mã.splice (i, 1); }}
Himanshu Shekhar

4

Với ES6 (hoặc sử dụng Babel hoặc Formscipt), bạn chỉ cần thực hiện:

var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);

https://es6console.com/j58euhbt/


Tôi đã đi đến cùng một cú pháp, một cách độc lập và chỉ sắp thêm nó như một giải pháp khi tôi tìm thấy cú pháp này. Nó có thể không phải là kinh tế nhất, nhưng nó đơn giản.
nize

4

Mã đơn giản với cú pháp ES6 (trả về mảng trùng lặp được sắp xếp):

let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};

Cách sử dụng:

duplicates([1,2,3,10,10,2,3,3,10]);

1
.filter () sẽ đơn giản hơn nhiều
tocqueville

4

lót

var arr = [9,1,2,4,3,4,9]
console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates


những gì indx!làm cho ví dụ đầu tiên?
saylestyler

1
@saylestyler Hehe, điều này có nghĩa indx !== ...- bất bình đẳng nghiêm ngặt.
Daria

chỉ thêm cho mảng các đối tượngresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix

4

Câu trả lời này cũng có thể hữu ích, nó tận dụng reduce toán tử / phương thức js để loại bỏ các bản sao khỏi mảng.

const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);

console.log(result);


3
bây giờ chúng ta có thể thực hiện new Set([1, 2, 2, 3, 3, 3, 3])để xóa các bản sao
kimbaudi

3

Hàm sau (một biến thể của hàm ElimD repeatates đã được đề cập) dường như thực hiện thủ thuật, trả về test2,1,7,5 cho đầu vào ["test", "test2", "test2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

Lưu ý rằng vấn đề lạ ở JavaScript hơn ở hầu hết các ngôn ngữ khác, bởi vì một mảng JavaScript có thể chứa bất cứ thứ gì. Lưu ý rằng các giải pháp sử dụng sắp xếp có thể cần cung cấp chức năng sắp xếp phù hợp - Tôi chưa thử tuyến đường đó.

Việc triển khai cụ thể này hoạt động đối với (ít nhất) chuỗi và số.

function findDuplicates(arr) {
    var i,
        len=arr.length,
        out=[],
        obj={};

    for (i=0;i<len;i++) {
        if (obj[arr[i]] != null) {
            if (!obj[arr[i]]) {
                out.push(arr[i]);
                obj[arr[i]] = 1;
            }
        } else {
            obj[arr[i]] = 0;            
        }
    }
    return out;
}

3

Chỉ ES5 (nghĩa là nó cần một bộ lọc () polyfill cho IE8 trở xuống):

var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];

arrayToFilter.
    sort().
    filter( function(me,i,arr){
       return (i===0) || ( me !== arr[i-1] );
    });

Tôi thích giải pháp đơn giản này. Tuy nhiên, nếu bạn muốn các bản sao, trước tiên bạn cần tìm các bản sao đó, sau đó làm cho danh sách trùng lặp là duy nhất. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (hàm (me, i, Array) {return (i! == 0 ) && (me == Array [i-1]);}). filter (hàm (tôi, i, Array) {return (i === 0) || (me! == Array [i-1]) ;});
Greg

3

var arr = [2, 1, 2, 2, 4, 4, 2, 5];

function returnDuplicates(arr) {
  return arr.reduce(function(dupes, val, i) {
    if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
      dupes.push(val);
    }
    return dupes;
  }, []);
}

alert(returnDuplicates(arr));

Hàm này tránh bước sắp xếp và sử dụng phương thức less () để đẩy các bản sao sang một mảng mới nếu nó không tồn tại trong đó.


3

Đây có lẽ là một trong những cách nhanh nhất để loại bỏ vĩnh viễn các bản sao khỏi một mảng nhanh gấp 10 lần so với hầu hết các chức năng ở đây. & Nhanh hơn 78 lần trong safari

function toUnique(a,b,c){//array,placeholder,placeholder
 b=a.length;
 while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
toUnique(array);
console.log(array);
  1. Kiểm tra: http://jsperf.com/wgu
  2. Bản trình diễn: http://jsfiddle.net/46S7g/
  3. Thêm: https://stackoverflow.com/a/25082874/2450730

nếu bạn không thể đọc mã ở trên, hãy đọc một cuốn sách javascript hoặc đây là một số giải thích về mã ngắn hơn. https://stackoverflow.com/a/21353032/2450730

EDIT Như đã nêu trong các bình luận, hàm này không trả về một mảng có dấu, tuy nhiên câu hỏi yêu cầu tìm các bản sao. trong trường hợp đó, một sửa đổi đơn giản cho hàm này cho phép đẩy các bản sao vào một mảng, sau đó sử dụng hàm trước đó toUniquesẽ loại bỏ các bản sao của các bản sao.

function theDuplicates(a,b,c,d){//array,placeholder,placeholder
 b=a.length,d=[];
 while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1))
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

toUnique(theDuplicates(array));

7
"Nếu bạn không thể đọc mã ở trên, hãy đọc một cuốn sách javascript" Câu trả lời này hoàn toàn có quá nhiều mã. Việc đặt tên các biến như a, b, c làm cho mã khó đọc. Từ bỏ niềng răng làm cho nó thậm chí còn tồi tệ hơn.
Sông Williamson

Hầu hết các câu trả lời của tôi đều dựa trên hiệu suất và tiết kiệm không gian (các giải pháp khác đã được đăng) ... nếu bạn không thích nó ... hãy học javascript, đọc sách js ... hoặc sử dụng jquery ... chúng có nhiều câu trả lời hơn nếu bạn tìm kiếm một giải pháp đơn giản. Nếu bạn thực sự muốn học một cái gì đó, tôi rất vui lòng giải thích ký tự mã cho mỗi chữ cái. Vì tôi không thể thấy một câu hỏi thực sự trong bình luận của bạn, tôi đoán bạn chỉ đang tìm kiếm một động lực để hạ thấp câu trả lời của tôi .... tiếp tục ... tôi không có vấn đề gì với điều đó. Đặt một câu hỏi thực sự hoặc cho tôi biết một cái gì đó không hoạt động với mã của tôi.
cocco

9
Không có gì sai về mặt kỹ thuật với mã của bạn. Điều đó nói rằng, đặt tên biến a, b, c, d, v.v. và xâu chuỗi trong khi các vòng lặp làm cho mã khó đọc. Vì vậy, mã không dạy được gì.
Sông Williamson

3

Sử dụng "bao gồm" để kiểm tra xem phần tử đã tồn tại chưa.

var arr = [1, 1, 4, 5, 5], darr = [], duplicates = [];

for(var i = 0; i < arr.length; i++){
  if(darr.includes(arr[i]) && !duplicates.includes(arr[i]))
    duplicates.push(arr[i])
  else
    darr.push(arr[i]);
}

console.log(duplicates);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>


Mã không trả lại các phần tử riêng biệt, nhưng không dẫn đến kết quả đã cho. Vui lòng cung cấp mã chính xác đầy đủ.
RWC

3

ES6 cung cấp cấu trúc dữ liệu Set, về cơ bản là một mảng không chấp nhận trùng lặp. Với cấu trúc dữ liệu Đặt, có một cách rất dễ dàng để tìm các bản sao trong một mảng (chỉ sử dụng một vòng lặp).

Đây là mã của tôi

function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
  for (let i = 0; i< arr.length; i++) {
     var size = set.size;
     set.add(arr[i]);
     if (set.size === size) {
         duplicates.add(arr[i]);
     }
  }
 return duplicates;
}

3

Tôi vừa tìm ra một cách đơn giản để đạt được điều này bằng bộ lọc Array

    var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    
    // Filter 1: to find all duplicates elements
    var duplicates = list.filter(function(value,index,self) {
       return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
    });
    
    console.log(duplicates);


3

Theo logic sẽ dễ dàng hơn và nhanh hơn

// @Param:data:Array that is the source 
// @Return : Array that have the duplicate entries
findDuplicates(data: Array<any>): Array<any> {
        return Array.from(new Set(data)).filter((value) => data.indexOf(value) !== data.lastIndexOf(value));
      }

Ưu điểm:

  1. Dòng đơn :-P
  2. Tất cả cấu trúc dữ liệu sẵn có giúp nâng cao hiệu quả
  3. Nhanh hơn

Mô tả logic:

  1. Chuyển đổi để thiết lập để loại bỏ tất cả các bản sao
  2. Lặp lại thông qua các giá trị được đặt
  3. Với mỗi lần kiểm tra giá trị được đặt trong mảng nguồn cho điều kiện "giá trị chỉ mục đầu tiên không bằng chỉ mục cuối cùng" ==> Sau đó suy ra là trùng lặp khác, đó là 'duy nhất'

Lưu ý: các phương thức map () và filter () hiệu quả và nhanh hơn.


1
Đã thử nghiệm điều này ... rất nhanh. và nó có ý nghĩa .. ước gì tôi nghĩ về nó
Michael Rhema
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.