รับค่าที่ไม่ซ้ำกันทั้งหมด (เช่น: ซ้ำกัน / มากกว่าหนึ่งเหตุการณ์) ในอาร์เรย์


418

ฉันต้องตรวจสอบอาร์เรย์ JavaScript เพื่อดูว่ามีค่าซ้ำกันหรือไม่ วิธีที่ง่ายที่สุดในการทำเช่นนี้คืออะไร? ฉันแค่ต้องค้นหาว่าค่าที่ซ้ำกันคืออะไร - ฉันไม่ต้องการดัชนีของพวกเขาหรือพวกเขาจะทำซ้ำกี่ครั้ง

ฉันรู้ว่าฉันสามารถวนซ้ำอาร์เรย์และตรวจสอบค่าอื่น ๆ ทั้งหมดสำหรับการแข่งขัน แต่ดูเหมือนว่าควรจะมีวิธีที่ง่ายขึ้น

คำถามที่คล้ายกัน:


22
ดูเหมือนจะมีความสับสนหลายปีเกี่ยวกับคำถามนี้ ฉันจำเป็นต้องรู้ว่าองค์ประกอบใดในอาเรย์นั้นมีการทำซ้ำ: "ฉันแค่ต้องการค้นหาสิ่งที่มีค่าซ้ำกัน" คำตอบที่ถูกต้องไม่ควรลบข้อมูลที่ซ้ำกันออกจากอาร์เรย์ นั่นคือสิ่งที่ตรงกันข้ามที่ฉันต้องการ: รายการที่ซ้ำกันไม่ใช่รายการขององค์ประกอบที่ไม่ซ้ำกัน
Scott Saunders

คำตอบ:


301

คุณสามารถจัดเรียงอาร์เรย์แล้วเรียกใช้ผ่านอาร์เรย์แล้วดูว่าดัชนีถัดไป (หรือก่อนหน้า) นั้นเหมือนกันกับปัจจุบันหรือไม่ สมมติว่าอัลกอริทึมการเรียงลำดับของคุณดีควรน้อยกว่า 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)}`);

ในกรณีที่คุณจะกลับมาเป็นฟังก์ชั่นการทำซ้ำ นี่สำหรับกรณีที่คล้ายกัน

การอ้างอิง: https://stackoverflow.com/a/57532964/8119511


10
"สมมติว่าอัลกอริทึมการเรียงลำดับของคุณดีสิ่งนี้ควรน้อยกว่า O ^ 2" โดยเฉพาะมันอาจเป็น O (n * log (n))
ESRogs

83
สคริปต์นี้ทำงานได้ไม่ดีนักเนื่องจากมีรายการซ้ำมากกว่า 2 รายการ (เช่นarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie

7
@swilliams i++ฉันไม่คิดว่าแนวทางเหล่านั้นพูดอะไรเกี่ยวกับไม่ได้ใช้ j = i + +jแต่พวกเขาบอกว่าจะไม่เขียน สองสิ่งที่แตกต่างกัน IMHO ผมคิดว่าi += 1มีมากขึ้นทำให้เกิดความสับสนกว่าเรียบง่ายและสวยงามi++:)
Danilo Bargen

34
-1 คำตอบนี้ผิดในหลาย ๆ ระดับ ประการแรกvar sorted_arr = arr.sort()คือไร้ประโยชน์: arr.sort()กลายพันธุ์อาร์เรย์เดิม (ซึ่งเป็นปัญหาในสิทธิของตนเอง) สิ่งนี้จะละทิ้งองค์ประกอบ (เรียกใช้รหัสด้านบนเกิดอะไรขึ้นกับ 9) cc @dystroy โซลูชันที่สะอาดกว่าน่าจะเป็นresults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException

24
ทุกคน: คำถามขอให้แสดงค่าที่ซ้ำกันไม่ใช่เพื่อลบออก โปรดอย่าแก้ไข / ทำลายรหัสเพื่อพยายามทำให้มันเป็นสิ่งที่ไม่ได้พยายามทำ การแจ้งเตือนควรแสดงค่าที่ซ้ำกัน
Scott Saunders

205

หากคุณต้องการทำให้ซ้ำซ้อนลองวิธีแก้ปัญหาที่ยอดเยี่ยมนี้:

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;
}

ที่มา: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/


18
นั่นเป็นรหัสที่ดี แต่น่าเสียดายที่มันไม่ได้ทำในสิ่งที่ฉันขอ
Scott Saunders

67
โค้ดด้านบน (ซึ่งเป็นของฉัน - นั่นคือบล็อกของฉัน) ทำให้คุณใกล้ชิด บิดเล็กน้อยและคุณอยู่ที่นั่น ก่อนอื่นคุณสามารถดูว่า arr.length และ out.length เหมือนกันหรือไม่ หากเหมือนกันไม่มีองค์ประกอบที่ซ้ำกัน แต่คุณต้องการอีกเล็กน้อย ถ้าคุณต้องการที่จะ "จับ" คู่ที่เกิดขึ้นตรวจสอบเพื่อดูว่าความยาวของอาร์เรย์เพิ่มขึ้นหลังจากที่ obj [arr [i]] = 0 บรรทัด ดีใช่มั้ย :-) ขอบคุณสำหรับคำพูดที่ดี Raphael Montanaro
Nosredna

6
@MarcoDemaio: เอ่อทำไมรหัสไม่ทำงานกับช่องว่าง? คุณสามารถใส่สิ่งที่คุณต้องการในชื่อคุณสมบัติ - เพียงแค่ไม่สามารถใช้ไวยากรณ์จุดเพื่อเข้าถึงคนที่มีช่องว่าง (หรืออุปกรณ์ประกอบฉากที่มีตัวละครอื่น ๆ ที่จะแยกวิเคราะห์)
Gijs

4
@Gijs: +1 คุณถูกต้อง ฉันไม่รู้ แต่มันก็ยังไม่ทำงานเมื่อเป็นอาเรย์ของวัตถุ
Marco Demaio

3
อัลกอริทึมนี้ยังมีผลข้างเคียงของการส่งคืนอาร์เรย์ที่เรียงลำดับซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ
ไม่สมมาตร

165

นี่คือคำตอบของฉันจากเธรดที่ซ้ำกัน (!):

เมื่อเขียนรายการนี้ 2014 - ตัวอย่างทั้งหมดเป็น for-loops หรือ jQuery Javascript มีเครื่องมือที่สมบูรณ์แบบสำหรับสิ่งนี้: เรียงลำดับแผนที่และลด

ค้นหารายการที่ซ้ำกัน

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' ]

ไวยากรณ์การทำงานเพิ่มเติม

@ Dmytro-Laptin ชี้ให้เห็นว่ารหัสบางส่วนถูกลบ นี่เป็นรหัสเดียวกันที่มีขนาดกะทัดรัดกว่า ใช้เทคนิค ES6 และฟังก์ชั่นการสั่งซื้อที่สูงขึ้น:

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
นี่เป็นวิธีการแก้ปัญหาที่ฉันกำลังมองหา ถ้าฉันต้องการมีโหลสำหรับลูปนั่นเป็นเรื่องง่ายที่จะเขียน คำสำคัญใน OP คือ "มีประสิทธิภาพ"
Josh

@ChristianLandgren ตัวแปร 'dict' ถูกประกาศที่ไหน ควรใช้ 'count' แทนหรือไม่
Dmytro Laptin

4
โปรดแสดงความคิดเห็นที่ทำให้เข้าใจผิดของคุณด้วยตัวคุณเอง (-1 สำหรับความหยิ่ง) ฉันเบื่อคนที่สับสน "สั้น" และ "มีประสิทธิภาพ" และโพสต์ตอร์ปิโดหนึ่งโดยไม่ต้องซักถามการแสดง โปรแกรมสั้นและ JS สมัยใหม่นั้นไม่ได้ดีไปกว่าธรรมชาติ การใช้คำผิด "ทั่วไป" ในที่นี้โดยทั่วไป ความเชื่อที่ไร้เดียงสาทั่วไปที่นี่ (อ่านความคิดเห็นต่อไปนี้) สาธิตที่นี่
ใบไม้

1
@leaf - โปรดตอบข้อเสนอแนะของคุณเอง โซลูชันที่คุณแก้ไขไม่สามารถอ่านได้อาจเป็น performant (อาจไม่ใช่) แต่ถึงกระนั้นการอ่านบ่อยครั้งก็สำคัญกว่าประสิทธิภาพในความคิดของฉัน แต่ที่สำคัญที่สุด - อย่าลบรหัสของบุคคลอื่นเพื่อแทนที่ด้วยของคุณโดยไม่มีเหตุผล
Christian Landgren

1
คำตอบที่ต่างกันใช่ความคิดเห็นต่างกันฉันไม่คิดอย่างนั้น
ใบไม้

64

ค้นหาค่าที่ซ้ำกันในอาร์เรย์

นี่ควรเป็นหนึ่งในวิธีที่สั้นที่สุดในการค้นหาค่าที่ซ้ำกันในอาร์เรย์ ตามที่ OP ร้องขอมาโดยเฉพาะสิ่งนี้จะไม่ลบรายการที่ซ้ำกัน แต่ค้นหาพวกมัน

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])

สิ่งนี้ไม่จำเป็นต้องเรียงลำดับหรือกรอบงานของบุคคลที่สาม นอกจากนี้ยังไม่ต้องการลูปแบบแมนนวล มันทำงานได้กับทุกค่าindexOf () (หรือจะชัดเจนกว่า: ตัวดำเนินการเปรียบเทียบที่เข้มงวด ) สนับสนุน

เพราะลด ()และindexOf ()มันต้องการอย่างน้อย IE 9


7
ES6 arrow / เวอร์ชั่นง่าย / บริสุทธิ์:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies

30

คุณสามารถเพิ่มฟังก์ชั่นนี้หรือปรับแต่งและเพิ่มไปยังต้นแบบ Array ของ 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);

นี่เป็นทางออกที่ดีที่สุด แต่ระวังการเพิ่มเข้าไปในอาเรย์ต้นแบบเพราะจะทำให้ IE สับสนหากวนลูปผ่านค่าต่างๆ
แซมสันสุโนนิน

@RoyTinker Perl สนับสนุนพวกเขาเกินไป แต่ฉันมีความคิดจาวาสคริปต์ได้
ลุค H

1
ไม่ทำสิ่งที่ OP ขอให้คืนสิ่งที่ซ้ำกัน
RWC

27

UPDATED: ข้อมูลต่อไปนี้ใช้กลยุทธ์แบบรวมที่ได้รับการเพิ่มประสิทธิภาพ มันปรับการค้นหาแบบดั้งเดิมจะได้รับประโยชน์จากเวลาการค้นหากัญชา (1) (การเรียกใช้uniqueบนอาร์เรย์แบบดั้งเดิมคือ O (n)) การค้นหาวัตถุได้รับการปรับให้เหมาะสมโดยการติดแท็กวัตถุด้วย id ที่ไม่ซ้ำกันในขณะที่วนซ้ำดังนั้นการระบุวัตถุที่ซ้ำกันก็คือ O (1) ต่อรายการและ O (n) สำหรับรายการทั้งหมด ข้อยกเว้นเพียงอย่างเดียวคือไอเท็มที่ถูกแช่แข็ง แต่มีน้อยและมีทางเลือกให้โดยใช้อาร์เรย์และ 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;
}();

หากคุณมีคอลเล็กชัน ES6 อยู่แสดงว่ามีเวอร์ชั่นที่ง่ายกว่าและเร็วกว่ามาก (shim สำหรับ IE9 + และเบราว์เซอร์อื่น ๆ ที่นี่: 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;
    }
  });
}

จริงๆ? ทำไมต้องตอบคำถามที่แก้ไปเมื่อ 2 ปีก่อน?
Rene Pot

3
ฉันกำลังตอบคำถามอื่นและเห็นได้ชัดว่ามีคนคลิกลิงค์ไปยังคนนี้โดยบังเอิญโดยบังเอิญเรียกว่าซ้ำซ้อนและจบการโคลนคำตอบของฉันและทำให้นรกสับสนในตัวเอง ฉันแก้ไขสิ่งต่าง ๆ มากมาย


16
ฉันคิดว่ามันดีกับการแก้ปัญหาที่แตกต่างกัน ไม่สำคัญว่าหัวข้อจะเก่าและแก้ไขได้เนื่องจากยังคงเป็นไปได้ที่จะเกิดขึ้นกับวิธีการต่าง ๆ ในการทำเช่นนี้ มันเป็นปัญหาทั่วไปทางวิทยาศาสตร์คอมพิวเตอร์
Emil Vikström

คุณอาจต้องการพูดถึงว่าสิ่งนี้อาศัยวิธีการ ES5 Array ที่ไม่ได้ใช้ใน IE <9.
Tim Down

24

UPDATED: สั้นหนึ่งซับเพื่อรับข้อมูลซ้ำ:

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

ในการรับอาร์เรย์โดยไม่มีการซ้ำซ้อนเพียงกลับเงื่อนไข:

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

ฉันไม่ได้คิดถึงfilter()คำตอบเก่าของฉันด้านล่าง;)


เมื่อสิ่งที่คุณต้องการคือการตรวจสอบว่าไม่มีการซ้ำซ้อนตามที่ถามในคำถามนี้คุณสามารถใช้every()วิธีการ:

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

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

โปรดทราบว่าevery()ใช้งานไม่ได้กับ IE 8 และด้านล่าง


1
ไม่ทำสิ่งที่ OP ขอให้คืนสิ่งที่ซ้ำกัน
RWC

จริงฉันปรับปรุงคำตอบของฉันเพื่อแก้ไข
Laurent Payot

ทางออกรอยัล! thnaks
Jeremy Piednoel

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

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

ดูเหมือนว่าจะใช้งานได้ แต่คุณควรรวมข้อความที่อธิบายวิธีการทำงาน
DIMM Reaper

1
จะไม่ทำงานหากมีค่าซ้ำกันมากกว่า 2 รายการ
vasa

1
นี่คือความหรูหราและเรียบง่าย ฉันรักมัน. สำหรับผู้ที่ต้องการทราบวิธีการทำงานฉันได้สร้างส่วนสำคัญที่แสดงวิธีการแสดงรายการที่ซ้ำกันและกำจัดรายการที่ซ้ำกัน ดูที่นี่: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Josh

@ TheDIMMReaper เป็นครั้งที่สอง'a'ในอาร์เรย์ภายในฟังก์ชั่นการกรองในindex == 1ขณะที่self.indexOf('a') == 0
Sergiy Ostrovsky

19

สิ่งนี้จะทำให้คุณได้ในสิ่งที่คุณต้องการ

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.


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)


ค้นหาค่าที่ไม่ซ้ำจาก 3 อาร์เรย์ (หรือมากกว่า):

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]

เพียงแค่ polyfill สำหรับ array indexOf สำหรับเบราว์เซอร์เก่า:

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;
  };
}

โซลูชัน jQuery โดยใช้ "inArray":

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

แทนการเพิ่ม Array.prototype.indexOf


+1 เพราะแน่นอนว่าสามารถอ่านรหัสได้โดยใช้ Array.indexOf แต่น่าเสียดายที่ดูเหมือนว่าจะช้ากว่าการใช้ลูปซ้อนแบบง่าย แม้แต่บนเบราว์เซอร์ที่ใช้ Array.indexOf เช่นเดียวกับ FF โปรดดูการทดสอบเหล่านี้ที่ฉันทำที่นี่: jsperf.com/array-unique2และแจ้งให้เราทราบความคิดของคุณ
Marco Demaio

@shekhardesigner - คำตอบที่ปรับปรุงแล้ว "r" เป็นอาร์เรย์ที่คุณค้นหาใน
vsync

@vsync ฉันต้องเริ่มต้นvar r = [];เพื่อให้รหัสของคุณทำงานได้ และทำงานเหมือนจับใจ
Shekhar K. Sharma

@shekhardesigner - ฉันขอโทษสำหรับการผสมสำหรับโซลูชัน Array Prototype คุณไม่จำเป็นต้องมีrตัวแปร
vsync

2
ไม่ทำสิ่งที่ OP ขอให้คืนสิ่งที่ซ้ำกัน
RWC

8

นี่คือทางออกที่ง่ายและหนึ่งบรรทัดของฉัน

มันจะค้นหาองค์ประกอบที่ไม่ซ้ำกันก่อนจากนั้นจึงสร้างอาร์เรย์ที่ไม่ซ้ำกันด้วยการใช้ชุด

ดังนั้นเราจึงมีรายการที่ซ้ำกันในที่สุด

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

นี่คือข้อเสนอของฉัน (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
สิ่งนี้จะรายงานว่าการเกิดขึ้นครั้งเดียวundefinedซ้ำกัน
Dem Pilafian

1
@DemPilafian ขอบคุณอัปเดต
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;});

หรือเมื่อเพิ่มเข้าไปใน 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;});}

ดูที่นี่: https://gist.github.com/1305056


1
ฟังก์ชันตัวกรองควรส่งคืนจริงหรือเท็จไม่ใช่องค์ประกอบเอง การกรองอาร์เรย์ที่มี 0 จะไม่ส่งคืน
mflodin

นอกจากนี้ฉันคิดว่าi&&มีไว้เพื่อหลีกเลี่ยงการออกนอกขอบเขตของอาร์เรย์ แต่ก็หมายความว่าองค์ประกอบแรกในอาร์เรย์ที่เรียงลำดับจะไม่รวมอยู่ด้วย ในตัวอย่างของคุณไม่มี1ในอาร์เรย์ผลลัพธ์ คือreturn i&&v!==o[i-1]?v:0;ควรจะเป็นreturn v!==o[i-1];
mflodin

6

วิธีที่รวดเร็วและสง่างามโดยใช้การทำลายและลดขนาดวัตถุ es6

มันทำงานใน O (n) (1 ซ้ำมากกว่าอาร์เรย์) และไม่ซ้ำค่าที่ปรากฏมากกว่า 2 ครั้ง

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

นี่เป็นวิธีที่ง่ายที่สุดที่ฉันคิดได้:

    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' ]

แค่นั้นแหละ.

บันทึก:

  1. สามารถใช้งานได้กับตัวเลขใด ๆ รวมถึง0สตริงและจำนวนลบเช่น-1- คำถามที่เกี่ยวข้อง: รับ ค่าที่ไม่ซ้ำทั้งหมดในอาร์เรย์ JavaScript (ลบรายการที่ซ้ำกัน)

  2. อาร์เรย์ดั้งเดิมarrถูกเก็บรักษาไว้ ( filterส่งคืนอาร์เรย์ใหม่แทนการแก้ไขต้นฉบับ)

  3. filteredอาร์เรย์มีทุกรายการที่ซ้ำกัน; มันสามารถมีค่าเดียวกันมากกว่า 1 ค่า (เช่นอาร์เรย์ที่กรองของเราที่นี่คือ[ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. หากคุณต้องการได้รับเฉพาะค่าที่ซ้ำกัน (คุณไม่ต้องการให้มีหลายรายการซ้ำด้วยค่าเดียวกัน) คุณสามารถใช้[...new Set(filtered)](ES6 มีชุดวัตถุซึ่งสามารถเก็บค่าที่ไม่ซ้ำกันเท่านั้น)

หวังว่านี่จะช่วยได้



4

นี่เป็นวิธีที่เบาและง่ายมาก:

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

คำตอบที่ดีที่สุด และหากผู้ใช้ต้องการองค์ประกอบที่ซ้ำกันอาร์เรย์สำหรับฉันนี้ปรับปรุง @brandon รหัส var ฉัน = รหัส. ความยาว; var ซ้ำ = []; ในขณะที่ (i -) {ถ้า (รหัส. indexOf (รหัส [i])! = i) {ถ้า (ซ้ำ .indexOf (รหัส [i]) === -1) {ซ้ำกัน. พุช (arr [i]) ; } codes.splice (i, 1); }}
Himanshu Shekhar

4

ด้วย ES6 (หรือใช้ Babel หรือ Typescipt) คุณสามารถทำได้:

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

https://es6console.com/j58euhbt/


ฉันมาที่ไวยากรณ์เดียวกันเป็นอิสระและเพิ่งจะเพิ่มเป็นวิธีแก้ปัญหาเมื่อฉันพบสิ่งนี้ มันอาจจะไม่ประหยัดที่สุด แต่ก็ง่าย
nize

4

รหัสอย่างง่ายพร้อมด้วยไวยากรณ์ ES6 (ส่งคืนอาร์เรย์ที่เรียงลำดับรายการที่ซ้ำกัน):

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};

วิธีใช้:

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

1
.filter () จะง่ายขึ้นมาก
tocqueville

4

หนึ่งในสายการบิน

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


สิ่งที่ไม่indx!ทำตัวอย่างแรก?
saylestyler

1
@saylestyler Hehe หมายถึงindx !== ...- ความไม่เท่าเทียมที่เข้มงวด
ดาเรีย

เพิ่มเฉพาะอาร์เรย์ของวัตถุresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix

4

คำตอบนี้อาจเป็นประโยชน์โดยใช้ประโยชน์จาก js reduce operator / methodเพื่อลบรายการที่ซ้ำกันออกจาก array

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

console.log(result);


3
ตอนนี้เราสามารถทำได้new Set([1, 2, 2, 3, 3, 3, 3])เพื่อลบรายการที่ซ้ำกัน
kimbaudi

3

ฟังก์ชั่นต่อไปนี้ (รูปแบบของฟังก์ชั่น ElimDuplicates ที่กล่าวถึงแล้ว) ดูเหมือนจะทำเคล็ดลับกลับมาทดสอบ 2,1,7,5 สำหรับการป้อนข้อมูล ["ทดสอบ", "test2", "test2", 1, 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

โปรดทราบว่าปัญหาเป็นคนแปลกหน้าใน JavaScript มากกว่าในภาษาอื่น ๆ ส่วนใหญ่เนื่องจากอาร์เรย์ JavaScript สามารถเก็บอะไรก็ได้ โปรดทราบว่าโซลูชันที่ใช้การเรียงลำดับอาจจำเป็นต้องจัดเตรียมฟังก์ชันการเรียงลำดับที่เหมาะสม - ฉันยังไม่ได้ลองเส้นทางนั้น

การใช้งานเฉพาะนี้ใช้งานได้กับสตริงและตัวเลข (อย่างน้อย)

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

ES5 เท่านั้น (เช่นต้องใช้ตัวกรอง () polyfill สำหรับ IE8 และด้านล่าง):

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] );
    });

ฉันชอบวิธีแก้ปัญหาง่ายๆนี้ ถ้าคุณต้องการรายการที่ซ้ำกันคุณต้องค้นหารายการที่ซ้ำกันก่อนแล้วจึงทำให้รายการที่ซ้ำกันไม่ซ้ำกัน [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). filter () (ฟังก์ชั่น (ฉัน, ฉัน, arr) {return (i! == 0 ) && (me == arr [i-1]);}) ตัวกรอง (ฟังก์ชั่น (ฉัน, i, arr) {return (i === 0) || (me! == arr [i-1]) ;});
เกร็ก

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));

ฟังก์ชันนี้จะหลีกเลี่ยงขั้นตอนการเรียงลำดับและใช้เมธอดลด () เพื่อส่งข้อมูลที่ซ้ำซ้อนไปยังอาร์เรย์ใหม่หากยังไม่มีอยู่ในนั้น


3

นี่อาจเป็นวิธีที่เร็วที่สุดในการลบรายการที่ซ้ำกันออกจากอาเรย์ 10 เท่าเร็วกว่าฟังก์ชั่นส่วนใหญ่ที่นี่ & ซาฟารี 78x เร็วขึ้น

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. ทดสอบ: http://jsperf.com/wgu
  2. การสาธิต: http://jsfiddle.net/46S7g/
  3. เพิ่มเติมได้ที่: https://stackoverflow.com/a/25082874/2450730

หากคุณไม่สามารถอ่านรหัสข้างต้นถามอ่านหนังสือจาวาสคริปต์หรือนี่คือคำอธิบายเกี่ยวกับรหัสที่สั้นกว่า https://stackoverflow.com/a/21353032/2450730

แก้ไข ตามที่ระบุไว้ในความคิดเห็นฟังก์ชั่นนี้จะส่งกลับอาร์เรย์ที่ไม่ซ้ำกับคำถาม แต่ขอให้ค้นหาซ้ำกัน ในกรณีนั้นการปรับเปลี่ยนอย่างง่าย ๆ ในฟังก์ชั่นนี้จะช่วยให้การซ้ำซ้อนลงในอาเรย์แล้วใช้ฟังก์ชั่นก่อนหน้านี้toUniqueจะลบรายการที่ซ้ำกันของซ้ำ

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
"ถ้าคุณไม่สามารถอ่านรหัสข้างบนถามอ่านหนังสือจาวาสคริปต์" มีรหัสกอล์ฟมากเกินไปในคำตอบนี้ การตั้งชื่อตัวแปรต่าง ๆ เช่น a, b, c ทำให้โค้ดอ่านยาก การดัดฟันเหล็กดัดที่ต่อเนื่องทำให้มันแย่ลง
River Williamson

คำตอบของฉันส่วนใหญ่ขึ้นอยู่กับประสิทธิภาพและการประหยัดพื้นที่ (โซลูชันอื่น ๆ ถูกโพสต์แล้ว) ... ถ้าคุณไม่ชอบมัน downvote ... อื่น ๆ เรียนรู้จาวาสคริปต์อ่านหนังสือ js ... หรือใช้ jquery ... พวกเขา มีคำตอบมากมายถ้าคุณค้นหาคำตอบง่ายๆ หากคุณต้องการเรียนรู้สิ่งที่ฉันมีความสุขที่จะอธิบายตัวอักษรรหัสต่อจดหมาย ในขณะที่ฉันไม่เห็นคำถามจริงในความคิดเห็นของคุณฉันเดาว่าคุณเพียงแค่ค้นหาแรงจูงใจที่จะลดคำตอบของฉัน .... ไปที่ ... ฉันไม่มีปัญหากับเรื่องนี้ ถามคำถามจริงหรือบอกสิ่งที่ไม่สามารถใช้ได้กับรหัสของฉัน
cocco

9
ไม่มีอะไรผิดพลาดทางเทคนิคกับรหัสของคุณ ที่กล่าวว่าการตั้งชื่อตัวแปร a, b, c, d, ฯลฯ และการผูกมัดในขณะที่ลูปทำให้โค้ดอ่านยาก ดังนั้นรหัสไม่สามารถสอนอะไรได้
River Williamson

3

การใช้ "รวม" เพื่อทดสอบว่ามีองค์ประกอบอยู่แล้ว

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>


รหัสไม่ให้องค์ประกอบที่แตกต่างกลับมา แต่ไม่นำไปสู่ผลลัพธ์ที่กำหนด กรุณาใส่รหัสให้ถูกต้อง
RWC

3

ES6 เสนอโครงสร้างข้อมูลชุดซึ่งโดยทั่วไปจะเป็นอาร์เรย์ที่ไม่ยอมรับการทำซ้ำ ด้วยโครงสร้างข้อมูล Set มีวิธีที่ง่ายมากในการค้นหารายการที่ซ้ำกันในอาร์เรย์ (ใช้วนเดียวเท่านั้น)

นี่คือรหัสของฉัน

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

ฉันเพิ่งค้นพบวิธีง่ายๆในการบรรลุสิ่งนี้โดยใช้ตัวกรอง 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

ตรรกะต่อไปนี้จะง่ายขึ้นและเร็วขึ้น

// @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));
      }

ข้อดี:

  1. บรรทัดเดียว :-P
  2. โครงสร้างข้อมูลแบบ inbuilt ทั้งหมดช่วยในการปรับปรุงประสิทธิภาพ
  3. ได้เร็วขึ้น

คำอธิบายของตรรกะ:

  1. การแปลงเป็นชุดเพื่อลบรายการซ้ำทั้งหมด
  2. วนซ้ำตามค่าที่ตั้งไว้
  3. ด้วยการตรวจสอบค่าแต่ละชุดในอาเรย์ของแหล่งข้อมูลสำหรับเงื่อนไข "ค่าดัชนีแรกไม่เท่ากับดัชนีสุดท้าย" ==> จากนั้นอนุมานว่าเป็นรายการซ้ำมันเป็น 'ไม่ซ้ำกัน'

หมายเหตุ: วิธีการ map () และ filter () นั้นมีประสิทธิภาพและเร็วขึ้น


1
ทดสอบสิ่งนี้ ... เร็วมาก และมันก็สมเหตุสมผลแล้ว .. หวังว่าฉันจะคิดถึงมัน
Michael Rhema
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.