รับค่าที่ไม่ซ้ำกันทั้งหมดในอาร์เรย์ JavaScript (ลบรายการที่ซ้ำกัน)


1485

ฉันมีจำนวนตัวเลขที่ฉันต้องการเพื่อให้แน่ใจว่าไม่ซ้ำกัน ฉันพบข้อมูลโค้ดด้านล่างบนอินเทอร์เน็ตและใช้งานได้ดีจนกระทั่งอาร์เรย์มีค่าเป็นศูนย์ ฉันพบสคริปต์อื่นนี้ที่นี่ใน Stack Overflow ที่มีลักษณะเกือบเหมือน แต่มันไม่ได้ล้มเหลว

ดังนั้นเพื่อช่วยในการเรียนรู้ใครบางคนสามารถช่วยฉันกำหนดว่าสคริปต์ต้นแบบจะผิดหรือเปล่า?

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

คำตอบเพิ่มเติมจากคำถามซ้ำ:

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


3
@hippietrail คำถามที่เก่ากว่านั้นเกี่ยวกับการค้นหาและส่งคืนข้อมูลที่ซ้ำกันเท่านั้น (ฉันก็สับสนเหมือนกัน!) คำถามของฉันเกี่ยวกับสาเหตุที่ฟังก์ชั่นนี้ล้มเหลวเมื่ออาร์เรย์มีค่าเป็นศูนย์
Mottie

คุณอาจต้องการทำให้ชื่อคำถามของคุณคลุมเครือน้อยลงเช่นกัน
hippietrail

สำหรับผู้อ่านในอนาคตเมื่อเริ่มพบว่าคุณต้องแก้ไขอัลกอริทึมเนื้อหาของโครงสร้างข้อมูลของคุณตลอดเวลา (สั่งพวกเขาลบองค์ประกอบที่ซ้ำกัน ฯลฯ ) หรือค้นหาองค์ประกอบที่อยู่ภายในทุก ๆ การวนซ้ำมันปลอดภัยที่จะสมมติว่าคุณ กำลังใช้โครงสร้างข้อมูลที่ไม่ถูกต้องตั้งแต่แรกและเริ่มใช้โครงสร้างที่เหมาะสมกับงานในมือมากกว่า (ในกรณีนี้คือชุดแฮชแทนที่จะเป็นอาร์เรย์)
nurettin

ฉันคัดลอกรหัสจากที่อื่นเวลา loooong ที่ผ่านมา ... แต่ดูเหมือนว่าตรงไปข้างหน้าสวย: o= object, a= array, i= indexและe= umm สิ่งที่: P
Mottie

คำตอบ:


2659

ด้วยJavaScript 1.6 / ECMAScript 5คุณสามารถใช้filterวิธีเนทีฟของ Array ด้วยวิธีต่อไปนี้เพื่อรับอาร์เรย์ที่มีค่าไม่ซ้ำกัน:

function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

พื้นเมืองวิธีประสงค์ห่วงผ่านอาร์เรย์และลารายการเฉพาะที่ผ่านการทำงานกลับได้รับfilteronlyUnique

onlyUniqueตรวจสอบว่าค่าที่กำหนดเป็นที่เกิดขึ้นครั้งแรก หากไม่ใช่จะต้องเป็นรายการซ้ำและจะไม่ถูกคัดลอก

โซลูชันนี้ทำงานได้โดยไม่ต้องมีไลบรารีพิเศษใด ๆ เช่น jQuery หรือ prototype.js

มันใช้งานได้กับอาร์เรย์ที่มีประเภทค่าแบบผสมเช่นกัน

สำหรับเบราว์เซอร์เก่า (<IE9) ที่ไม่สนับสนุนวิธีพื้นเมืองfilterและindexOfคุณสามารถหา arounds ทำงานในเอกสาร MDN สำหรับกรองและindexOf

หากคุณต้องการที่จะให้เกิดขึ้นครั้งล่าสุดของค่าง่ายแทนที่โดยindexOflastIndexOf

ด้วย ES6 มันสามารถย่อให้สั้นลงได้:

// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i); 

// unique is ['a', 1, 2, '1']

ขอบคุณCamilo Martinสำหรับคำแนะนำในความคิดเห็น

ES6 มีวัตถุดั้งเดิมSetเพื่อเก็บค่าที่ไม่ซ้ำ ในการรับอาร์เรย์ที่มีค่าไม่เหมือนใครคุณสามารถทำได้ดังนี้:

var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)]; 

// unique is ['a', 1, 2, '1']

ตัวสร้างของSetใช้วัตถุที่วนซ้ำได้เช่น Array และตัวดำเนินการการแพร่กระจาย...เปลี่ยนชุดกลับไปเป็น Array ขอบคุณLukas Lieseสำหรับคำแนะนำในความคิดเห็น


53
วิธีนี้จะทำงานช้าลงอย่างน่าเสียดาย คุณวนซ้ำสองครั้งพร้อมตัวกรองและดัชนีของ
Jack Franzen

18
@ JackFranzen ช้ากว่าอะไร? ทางออกจากราฟาเอล ? โซลูชันRafaelsไม่สามารถใช้งานกับอาร์เรย์แบบผสมได้ สำหรับตัวอย่างของฉันคุณจะได้รับ['a', 1, 'a', 2, '1'] ['a', 1, 2]แต่นี่ไม่ใช่สิ่งที่ฉันคาดไว้ BTW ช้ากว่ามากสัมพันธ์กันมาก
TLindig

25
ใน JS สมัยใหม่: .filter((v,i,a)=>a.indexOf(v)==i)(สัญลักษณ์ลูกศรไขมัน)
Camilo Martin

163
let unique_values = [...new Set(random_array)]; developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

5
สำหรับคำตอบที่ละเอียดยิ่งขึ้นรวมถึงความเป็นไปได้มากมายเช่นการเรียงลำดับก่อนและจัดการกับชนิดข้อมูลที่หลากหลาย - ดูstackoverflow.com/a/9229821/368896
Dan Nissenbaum

874

อัปเดตคำตอบสำหรับ ES6 / ES2015 : การใช้ชุดโซลูชันบรรทัดเดียวคือ:

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

ซึ่งผลตอบแทน

[4, 5, 6, 3, 2, 23, 1]

ตามที่แนะนำle_mสิ่งนี้สามารถสั้นลงได้โดยใช้ตัวดำเนินการสเปรดเช่น

var uniqueItems = [...new Set(items)]

10
โปรดสังเกตว่าอาร์เรย์ภายในจะไม่ทำงานArray.from(new Set([[1,2],[1,2],[1,2,3]]))
Alexander Goncharov

2
ผลการดำเนินงานของการแก้ปัญหานี้เมื่อเทียบกับmyArray.filter((v, i, a) => a.indexOf(v) === i);?
Simoyw

42
โปรดทราบว่าถ้าคุณใช้Setและเพิ่มวัตถุแทนค่าดั้งเดิมมันจะมีการอ้างอิงที่ไม่ซ้ำกับวัตถุ ดังนั้นการตั้งค่าsในlet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);จะส่งคืนสิ่งนี้: Set { { Foo: 'Bar' }, { Foo: 'Bar' } }ซึ่งเป็นSetวัตถุที่มีเอกลักษณ์อ้างอิงถึงวัตถุที่มีค่าเดียวกัน หากคุณเขียนlet o = {Foo:"Bar"};และสร้างชุดที่มีการอ้างอิงสองรายการดังนี้: ดังนั้นlet s2 = new Set([o,o]);s2 จะเป็นเช่นนั้นSet { { Foo: 'Bar' } }
2560

2
ตัวเลือกทั้งสองนี้มีปัญหาใน IE10 แม้จะมีชั้น polyfill.io อยู่
Thymine

2
กรณีทดสอบใหม่jsperf.com/array-filter-unique-vs-new-set/1ดูเหมือนว่าจะnew Setเป็นถ้วยรางวัลของ
5391

167

ฉันรู้ว่าคำถามนี้มีคำตอบมากกว่า 30 ข้อแล้ว แต่ฉันได้อ่านคำตอบที่มีอยู่ทั้งหมดก่อนแล้วจึงค้นคว้าด้วยตัวเอง

ฉันแบ่งคำตอบทั้งหมดเป็น 4 คำตอบที่เป็นไปได้:

  1. ใช้คุณสมบัติ ES6 ใหม่: [...new Set( [1, 1, 2] )];
  2. ใช้วัตถุ{ }เพื่อป้องกันการซ้ำซ้อน
  3. ใช้ตัวช่วยอาร์เรย์ [ ]
  4. ใช้ filter + indexOf

นี่คือตัวอย่างรหัสที่พบในคำตอบ:

ใช้คุณสมบัติ ES6 ใหม่: [...new Set( [1, 1, 2] )];

function uniqueArray0(array) {
  var result = Array.from(new Set(array));
  return result    
}

ใช้วัตถุ{ }เพื่อป้องกันการซ้ำซ้อน

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

ใช้ตัวช่วยอาร์เรย์ [ ]

function uniqueArray2(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

ใช้ filter + indexOf

function uniqueArray3(a) {
  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }

  // usage
  var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

  return unique;
}

และฉันสงสัยว่าอันไหนเร็วกว่ากัน ฉันได้สร้างตัวอย่าง Google ชีตเพื่อทดสอบฟังก์ชั่น หมายเหตุ: ECMA 6 ไม่สามารถใช้ได้ใน Google ชีตดังนั้นฉันไม่สามารถทดสอบได้

นี่คือผลการทดสอบ: ป้อนคำอธิบายรูปภาพที่นี่

ฉันคาดว่าจะเห็นรหัสที่ใช้วัตถุ{ }จะชนะเพราะใช้แฮช ดังนั้นฉันดีใจที่การทดสอบแสดงผลลัพธ์ที่ดีที่สุดสำหรับอัลกอริทึมนี้ใน Chrome และ IE ขอขอบคุณที่ @rab สำหรับรหัส


ตัวเลือก "filter + indexOf" ช้ามากในอาร์เรย์ที่มีมากกว่า 100,000 รายการ ฉันต้องใช้ "แผนที่วัตถุ" วิธี แต่มันแบ่งการเรียงลำดับเดิม
อิสรภาพ

จำนวนที่สูงกว่านั้นช้าลงไม่ใช่เร็วขึ้นหรือไม่
fletchsod

3
@ fletchsod ตัวเลขเป็นเวลา ms ในการเรียกใช้รหัส
Max Makhrov

1
ตัวเลขนั้นมีวงศ์! สคริปต์ของ Google apps ทำงานบนเซิร์ฟเวอร์ไม่ใช่ในเบราว์เซอร์ของลูกค้าดังนั้นประสิทธิภาพของ Chrome / IE (หรือเบราว์เซอร์ใด ๆ ) จะเหมือนกัน!
Jay Dadhania

1
แม้ว่าจะเป็นไปได้ที่จะเรียกใช้ JS ฝั่งไคลเอ็นต์จาก Google Script (ผ่านทางgoogle.script.hostหรือgoogle.script.run - ไม่แน่ใจว่าที่ใด) คำตอบระบุอย่างชัดเจนว่า"ECMA 6 ไม่สามารถใช้ได้ใน Google ชีต" - ดังนั้น เราสามารถสรุปได้อย่างปลอดภัยว่าผู้ลงประกาศใช้ Google Script ฝั่งเซิร์ฟเวอร์สำหรับเรื่องนี้และดังนั้นคำตอบก็แสดงให้เห็นถึงประสิทธิภาพของ Google Server ไม่ใช่ของเบราว์เซอร์ !!
Jay Dadhania

134

นอกจากนี้คุณยังสามารถใช้underscore.js

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

ซึ่งจะกลับมา:

[1, 2, 3, 4]

22
กรุณาทำคนนี้ อย่าแจ็คบางอย่างลงบนต้นแบบ Array โปรด.
Jacob Dalton

5
@JacobDalton - นี่ไม่ได้เป็นการขยายต้นแบบ Array มันเป็น namespaced ใน _ วัตถุ
superluminary

24
@superluminary ฉันรู้ว่านั่นเป็นเหตุผลที่ฉันพูดได้โปรดทำสิ่งนี้ โซลูชันที่ได้รับการยอมรับจะแนะนำการแก้ไขต้นแบบ Array อย่าทำอย่างนั้น
Jacob Dalton

20
@JacobDalton โปรดอย่าทำเช่นนี้ ไม่จำเป็นต้องเพิ่มห้องสมุดพิเศษเฉพาะสำหรับงานเล็ก ๆ ที่สามารถทำได้ด้วยarray = [...new Set(array)]

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

68

หนึ่งไลเนอร์ Pure JavaScript

ด้วยไวยากรณ์ ES6

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

ป้อนคำอธิบายรูปภาพที่นี่

ด้วยไวยากรณ์ ES5

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

ความเข้ากันได้ของเบราว์เซอร์ : IE9 +


13
@Spets มันมีราคากำลังสองดังนั้นมันจึงไม่ใช่คำตอบที่ดีที่สุด
Oriol

@Spets ชอบไม่เหมือนใคร / แตกต่าง ... ใช่, ฉลาด, ใช้ radix เพื่อเรียงลำดับแรก, ช้ากว่า 0 (n2) quicksearch ในกรณีส่วนใหญ่
doker

ขอบคุณเพื่อน! ไม่ได้ตระหนักถึงมันเมื่อฉันดูรหัสครั้งแรก แต่ตอนนี้มันค่อนข้างชัดเจนมากขึ้น
Spets

51

ฉันได้พบวิธีที่ดีที่ใช้ jQuery

arr = $.grep(arr, function(v, k){
    return $.inArray(v ,arr) === k;
});

หมายเหตุ: รหัสนี้ถูกดึงจากโพสต์การชกต่อยของ Paul ไอริช - ฉันลืมที่จะให้เครดิต: P


8
โซลูชันที่รัดกุม แต่การเรียกใช้ inArray นั้นมีประสิทธิภาพน้อยกว่าการเรียก hasOwnProperty
มิสเตอร์สมิ ธ

นี่ก็เป็น O (N ^ 2) ด้วยใช่ไหม ในขณะที่พจนานุกรมหรือวิธี hasOwnProperty น่าจะเป็น O (N * logN)
เพลท

สิ่งนี้ใช้ได้กับฉันโซลูชันอื่น ๆ ทั้งหมดไม่ได้รับการสนับสนุนให้เป็น Internet Explorer
kerl

51

ทางออกที่สั้นที่สุดด้วย ES6: [...new Set( [1, 1, 2] )];

หรือถ้าคุณต้องการแก้ไขต้นแบบ Array (เช่นในคำถามเดิม):

Array.prototype.getUnique = function() {
    return [...new Set( [this] )];
};

EcmaScript 6 มีการใช้งานเพียงบางส่วนในเบราว์เซอร์สมัยใหม่ในขณะนี้ (สิงหาคม 2015) แต่เป็นBabelได้กลายเป็นที่นิยมอย่างมากสำหรับการเปลี่ยน ES6 (หรือแม้แต่ ES7) กลับไปเป็น ES5 ด้วยวิธีนี้คุณสามารถเขียนโค้ด ES6 ได้วันนี้!

หากคุณสงสัยว่าความ...หมายของมันเรียกว่าตัวดำเนินการสเปรด จากMDN : «ตัวดำเนินการสเปรดช่วยให้สามารถขยายนิพจน์ได้ในที่ซึ่งมีอาร์กิวเมนต์หลายตัว (สำหรับการเรียกใช้ฟังก์ชัน) หรือองค์ประกอบหลายอย่าง (สำหรับตัวอักษรแถวลำดับ) ที่คาดหวัง» เนื่องจาก Set เป็น iterable (และสามารถมีค่าที่ไม่ซ้ำกันได้) ผู้ดำเนินการกระจายจะขยาย Set เพื่อเติมอาร์เรย์

แหล่งข้อมูลเพื่อการเรียนรู้ ES6:


3
คุณสามารถทำได้แม้จะสั้นกว่าด้วยa = [...Set(a)]แต่อย่างไรก็ตามนี่คือ Firefox เท่านั้นสำหรับตอนนี้
c69

@ c69 ใช่จะไม่สั้นกว่านั้น ผู้ใช้ SpiderMonkey จะประทับใจเช่นกัน
Torsten Becker

ทำงานร่วมกับ Babel คุณเพียงแค่ต้องใส่ Array.from shim ด้วย:require ( "core-js/fn/array/from" );
Vladislav Rastrusny

Array.prototype.getUnique = function () {return [... new Set ([this])]]; }; หรือ Array.prototype.getUnique = function () {return [... new Set (this)]; }; ฉันใช้มันกับ $ - ('ร่างกาย'). html (). toLowerCase (). match (/ ([a-zA-Z0-9 ._ + -] + @ [a-zA-Z0-9) . _-] + \ [a-zA-Z0-9 ._-] +) / GI) .getUnique (); อันแรกคืนค่าที่ไม่ซ้ำใครให้ฉันเฉพาะที่อันที่สองคืนค่าการลบข้อมูลที่ซ้ำกันทั้งหมด
ashique

[...Set(['a', 1, 'a', 2, '1'])]จะโยน TypeError ดังนั้นจึงควรเก็บnew:[...new Set(['a', 1, 'a', 2, '1'])]
Adam Katz

36

วิธีที่ง่ายที่สุด:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);

หรือ:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));


4
โปรดทราบว่าไม่รองรับ IE10 และด้านล่าง โปรดทราบว่า IE11 + และ Safari ให้การสนับสนุนที่ จำกัด (ไม่แน่ใจว่าตัวอย่างข้างต้นใช้งานได้) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

32

วิธีที่ง่ายที่สุดและเร็วที่สุด (ใน Chrome) ในการทำสิ่งนี้:

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

เพียงแค่ผ่านทุกรายการในอาเรย์ทดสอบว่ามีไอเท็มนั้นอยู่ในรายการแล้วหรือไม่หากไม่อยู่ให้เลื่อนไปที่อาร์เรย์ที่ได้รับคืน

ตาม jsPerf ฟังก์ชั่นนี้เร็วที่สุดในบรรดาที่ฉันสามารถหาได้ทุกที่ - อย่าลังเลที่จะเพิ่มของคุณเอง

รุ่นที่ไม่ใช่ต้นแบบ:

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

การเรียงลำดับ

เมื่อต้องการเรียงลำดับอาเรย์ต่อไปนี้เป็นวิธีที่เร็วที่สุด:

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

หรือไม่ใช่ต้นแบบ:

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

นี่ยังเร็วกว่าวิธีการข้างต้นในเบราว์เซอร์ที่ไม่ใช่ Chrome ส่วนใหญ่


บน Linux นั้น Chrome 55.0.2883 ชอบ arr.unique () และ swilliams 'arrclone2.sortFilter () ของคุณช้าที่สุด (ช้ากว่า 78%) อย่างไรก็ตาม Firefox 51.0.0 (พร้อมแอดออนจำนวนมาก) นั้นมีความเร็วสูงที่สุด (ยังคงช้ากว่า Ops / วินาทีมากกว่าผลการค้นหาอื่น ๆ ของ Chrome) โดยมีjQuery $ .grep (arr, jqFilter) ของ mottieช้าที่สุด (46% ช้ากว่า) arr.uniq ของคุณช้ากว่า 30% ฉันทำการทดสอบแต่ละครั้งสองครั้งและได้ผลลัพธ์ที่สอดคล้องกัน Rafael's arr.getUnique ()ได้อันดับสองในเบราว์เซอร์ทั้งสอง
Adam Katz

jsPerf เป็นรถในขณะนี้ดังนั้นการแก้ไขของฉันในการทดสอบนี้ไม่ได้กระทำทุกอย่าง แต่มันก็ส่งผลให้เกิดการเพิ่มการทดสอบสอง: Cocco ของtoUnique ()เต้น Vamsi ของES6 list.filter ()บนเบราว์เซอร์ทั้งเต้น sortFilter swilliams' () สำหรับ # 1 บน FF (sortFilter ช้ากว่า 16%) และการทดสอบที่จัดเรียงของคุณ (ซึ่งช้ากว่า 2%) สำหรับ # 3 บน Chrome
Adam Katz

อ่าฉันไม่ทันว่าการทดสอบเหล่านั้นมีขนาดเล็กและไม่สำคัญ ความคิดเห็นต่อคำตอบที่ได้รับการยอมรับอธิบายถึงปัญหาและเสนอการแก้ไขในการทดสอบซึ่งรหัสของ Rafael นั้นเร็วที่สุดและรหัส arr.unique ของ Joetje50 ช้ากว่า 98% ฉันได้แก้ไขอีกครั้งตามที่ระบุไว้ในความคิดเห็นนี้
Adam Katz

1
จริงๆแล้วอัลกอริทึมที่คุณใช้ในuniqueฟังก์ชั่นนั้นมีความซับซ้อน O (n ^ 2) ในขณะที่หนึ่งในgetUniqueนั้นคือ O (n) ชุดแรกอาจเร็วกว่าชุดข้อมูลขนาดเล็ก แต่คุณจะโต้แย้งกับคณิตศาสตร์ได้อย่างไรคุณสามารถตรวจสอบให้แน่ใจว่าชุดหลังเร็วกว่านี้หากคุณเรียกใช้ชุดข้อมูลจำนวนมาก 1e5
Mikhail Dudin

31

มีประสิทธิภาพเท่านั้น! รหัสนี้อาจเร็วกว่ารหัส 10 เท่าที่นี่ * ใช้ได้กับเบราว์เซอร์ทั้งหมดและมีผลต่อหน่วยความจำต่ำสุด .... และอีกมากมาย

หากคุณไม่ต้องการนำอาเรย์เก่ามาใช้ซ้ำ btw ทำการดำเนินการอื่น ๆ ที่จำเป็นก่อนที่คุณจะแปลงมันให้มีลักษณะเฉพาะที่นี่อาจเป็นวิธีที่เร็วที่สุดในการทำเช่นนี้

var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

จากนั้นคุณสามารถลองสิ่งนี้

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

function toUnique(a, b, c) { //array,placeholder,placeholder
  b = a.length;
  while (c = --b)
    while (c--) a[b] !== a[c] || a.splice(c, 1);
  return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]

ฉันมากับฟังก์ชั่นนี้อ่านบทความนี้ ...

http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/

ฉันไม่ชอบ for for loop มันมีพารามิเตอร์หลายตัวฉันชอบห่วง - ในขณะที่การวนซ้ำเร็วที่สุดในเบราว์เซอร์ทั้งหมดยกเว้นที่เราชอบ ... โครมมาก

ต่อไปฉันเขียนฟังก์ชั่นแรกที่ใช้ในขณะที่และมันเร็วกว่าฟังก์ชั่นที่พบในบทความ แต่ไม่เพียงพอunique2()

ขั้นตอนต่อไปใช้ js ที่ทันสมัย Object.keys ฉันแทนที่อันอื่นสำหรับลูปด้วย Object.keys ของ js1.7 ... เร็วขึ้นและสั้นลงเล็กน้อย (เร็วกว่าโครเมี่ยม 2x);) ไม่พอ!. unique3().

ณ จุดนี้ฉันคิดว่าสิ่งที่ฉันต้องการในฟังก์ชั่นพิเศษของฉัน ฉันไม่ต้องการอาเรย์เก่าฉันต้องการฟังก์ชั่นที่รวดเร็ว ดังนั้นฉันจึงใช้ 2 ในขณะที่ลูป + ประกบกันunique4()

ไม่มีประโยชน์ที่จะบอกว่าฉันประทับใจ

โครเมียม:การดำเนินงานปกติ 150,000 ต่อวินาทีเพิ่มขึ้นเป็น 1,800,000 การปฏิบัติการต่อวินาที

เช่น: 80,000 op / s และ 3,500,000 op / s

ios: 18,000 op / s เทียบกับ 170,000 op / s

ซาฟารี: 80,000 op / s และ 6,000,000 op / s

หลักฐาน http://jsperf.com/wguหรือดีกว่าใช้ console.time ... microtime ... อะไรก็ตาม

unique5() เป็นเพียงการแสดงให้คุณเห็นว่าเกิดอะไรขึ้นถ้าคุณต้องการเก็บอาเรย์เก่าไว้

อย่าใช้Array.prototypeถ้าคุณไม่รู้ว่าคุณกำลังทำอะไรอยู่ ฉันเพิ่งทำสำเนาและผ่านมามากมาย ใช้Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})หากคุณต้องการสร้างต้นแบบดั้งเดิมตัวอย่าง: https://stackoverflow.com/a/20463021/2450730

การสาธิต http://jsfiddle.net/46S7g/

หมายเหตุ: อาเรย์เก่าของคุณถูกทำลาย / กลายเป็นความแปลกใหม่หลังจากการดำเนินการนี้

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

บางส่วนจะใช้indexOf ... ไม่ ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh

สำหรับอาร์เรย์ที่ว่างเปล่า

!array.length||toUnique(array); 

4
ทดสอบบน node.js พร้อมกับอาร์เรย์ Urk (สตริง) 100k ผลที่ได้คือ 2x ช้ากว่า underscore.js _.uniq ... แม้ว่า jsperf แยกต่างหากเห็นด้วยกับคุณ ( jsperf.com/uniq-performance/5 ) ฉันผิดหวัง :(
xShirase

3
คุณไม่ได้ทดสอบอย่างถูกต้องใน jsperf ... ในตัวอย่างของคุณคุณกำหนดฟังก์ชั่นทุกครั้ง ... แต่ฟังก์ชั่น underscore.js มีการกำหนดไว้แล้ว .. นี่เป็นการลงโทษหน้าที่ของฉัน ทดสอบ 3 และ 4 อีกอย่างที่ฉันควรจะบอกคือถ้าคุณใช้ตัวแปรผสม (สตริง & ตัวเลข) คุณควรแทนที่ [b]! == a [c] ด้วย [b]! = a [c]
cocco

2
ฉันไม่แน่ใจว่า jsPerf นั้นถูกต้องหรือไม่ แต่ดูเหมือนว่าทางเลือกลด (สำหรับฉันนั้นง่ายกว่าที่จะเข้าใจ) ค่อนข้างเร็วกว่าโซลูชันของคุณถึง 94% jsperf.com/reduce-for-distinctแก้ไข: คุณทำงานช้าลงใน Chrome, เหมือนกันบน Edge และเร็วกว่าบน Firefox
Victor Ivens

3
สามารถใช้งานได้เฉพาะกับอาร์เรย์ขนาดเล็ก / เปอร์เซ็นต์ต่ำที่ซ้ำกัน แต่ละวัตถุเวลาที่ไม่ซ้ำกันได้รับพบว่าเครื่องยนต์จะถูกบังคับให้เปลี่ยนทั้งหมดขององค์ประกอบส่วนที่เหลือไปทางซ้ายโดย: 1) การทำซ้ำมากกว่าพวกเขา 2) อ่านพวกเขา 3) เขียนไปยังสถานที่ใหม่ จากนั้นมันยังสร้างอาร์เรย์ใหม่ที่มีองค์ประกอบที่เชื่อมต่อกันแล้วส่งกลับเป็นผลลัพธ์ ... อัลกอริทึมจะลดขนาดอย่างรวดเร็วด้วยอาร์เรย์ที่ใหญ่กว่า / ซ้ำซ้อนกันมากขึ้น สำหรับอาร์เรย์ที่มีขนาด 1,000-> 10,000-> 50000 และซ้ำกัน ~ 40% เวลาที่ใช้โดยเฉลี่ยจะอยู่ที่ 2-> 775-> 19113 ms (ขนาดเปลี่ยนเป็น 1-> x10-> x5 เวลาเป็น 1-> x10-> x25) ใน Chrome
ankhzet

1
ขอบคุณ วิธีการที่ดี แต่สิ่งที่เกี่ยวกับการสั่งซื้อรายการที่ถูกต้อง?
อิสรภาพ

28

คำตอบมากมายที่นี่อาจไม่มีประโยชน์สำหรับผู้เริ่มต้น ถ้าการทำซ้ำอาร์เรย์เป็นเรื่องยากพวกเขาจะรู้เกี่ยวกับห่วงโซ่ต้นแบบหรือแม้กระทั่ง jQuery หรือไม่

ในเบราว์เซอร์สมัยใหม่โซลูชันที่สะอาดและเรียบง่ายคือการจัดเก็บข้อมูลในชุดซึ่งออกแบบมาเพื่อรายการค่าที่ไม่ซ้ำกัน

const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));

สิ่งArray.fromนี้มีประโยชน์ในการแปลง Set กลับเป็น Array เพื่อให้คุณสามารถเข้าถึงวิธีการที่ยอดเยี่ยมทั้งหมดที่มีในอาร์เรย์ได้อย่างง่ายดาย นอกจากนี้ยังมีวิธีอื่นในการทำสิ่งเดียวกัน แต่คุณอาจไม่ต้องการArray.fromเลยเพราะชุดมีคุณสมบัติที่มีประโยชน์มากมายเช่นforEach forEach

หากคุณต้องการสนับสนุน Internet Explorer รุ่นเก่าดังนั้นจึงไม่สามารถใช้การตั้งค่าได้เทคนิคง่ายๆคือการคัดลอกรายการต่างๆไปยังอาร์เรย์ใหม่ในขณะที่ตรวจสอบก่อนว่าพวกเขาอยู่ในอาร์เรย์ใหม่แล้วหรือไม่

// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];

// Go through each car, one at a time.
cars.forEach(function (car) {
    // The code within the following block runs only if the
    // current car does NOT exist in the uniqueCars list
    // - a.k.a. prevent duplicates
    if (uniqueCars.indexOf(car) === -1) {
        // Since we now know we haven't seen this car before,
        // copy it to the end of the uniqueCars list.
        uniqueCars.push(car);
    }
});

ในการทำให้สิ่งนี้สามารถนำกลับมาใช้ใหม่ได้ทันทีให้วางไว้ในฟังก์ชั่น

function deduplicate(data) {
    if (data.length > 0) {
        var result = [];

        data.forEach(function (elem) {
            if (result.indexOf(elem) === -1) {
                result.push(elem);
            }
        });

        return result;
    }
}

เพื่อกำจัดสิ่งที่ซ้ำกันตอนนี้เราจะทำเช่นนี้

var uniqueCars = deduplicate(cars);

deduplicate(cars)ส่วนหนึ่งจะกลายเป็นสิ่งที่เราตั้งชื่อผลเมื่อเสร็จสิ้นการทำงาน

เพียงแค่ส่งชื่ออาร์เรย์ที่คุณต้องการ


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

20
["Defects", "Total", "Days", "City", "Defects"].reduce(function(prev, cur) {
  return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
 }, []);

[0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
  return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
 }, []);

คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงไม่ได้เป็นเพียงแค่pushองค์ประกอบไปยังอาร์เรย์แทนที่จะใช้concat? ฉันลองกดแล้วก็ล้มเหลว ฉันกำลังมองหาคำอธิบาย
makenova

1
เหตุผลอยู่ในค่าส่งคืน concat ส่งคืนอาเรย์ที่ถูกแก้ไข (สิ่งที่ต้องการคืนภายในฟังก์ชันลด) ในขณะที่ push ส่งคืนดัชนีที่คุณสามารถเข้าถึงค่าที่ถูกผลัก นั่นตอบคำถามของคุณหรือไม่
sergeyz

เห็นได้ชัดว่าการแก้ปัญหานี้ค่อนข้างเร็วในโครเมี่ยม (และโหนด) jsperf.com/reduce-for-distinctนั่นเป็นเวอร์ชั่น ES6: [0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
Victor Ivens

ด้านหมายเหตุ: การดำเนินการนี้ไม่เป็นNaNมิตร
Alireza

19

เราสามารถทำได้โดยใช้ชุด ES6:

var duplicatedArray = [1, 2, 3, 4, 5, 1, 1, 1, 2, 3, 4];
var uniqueArray = Array.from(new Set(duplicatedArray));

console.log(uniqueArray);

// ผลลัพธ์จะเป็น

uniqueArray = [1,2,3,4,5];

17

ต้นแบบgetUniqueนี้ไม่ถูกต้องทั้งหมดเพราะถ้าฉันมีอาร์เรย์เหมือน: ["1",1,2,3,4,1,"foo"]มันจะกลับมา["1","2","3","4"]และ"1"เป็นสตริงและ1เป็นจำนวนเต็ม; พวกเขาแตกต่าง.

นี่คือทางออกที่ถูกต้อง:

Array.prototype.unique = function(a){
    return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });

โดยใช้:

var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();

["1",2,3,4,1,"foo"]จะผลิตดังกล่าวข้างต้น


1
โปรดทราบว่า$foo = 'bar'เป็นวิธี PHP ในการประกาศตัวแปร มันจะทำงานใน javascript แต่จะสร้างทั่วโลกโดยปริยายและโดยทั่วไปไม่ควรทำ
Camilo Martin

@CamiloMartin ขออภัย แต่คุณผิด $ foo เป็นคนทั่วโลกเพราะตัวอย่างไม่ได้ปิดและเขาไม่มีคำหลัก var ไม่มีอะไรเกี่ยวข้องกับดอลลาร์jsfiddle.net/robaldred/L2MRb
Rob

8
@ Rob นั่นคือสิ่งที่ฉันพูดคน PHP จะคิดว่า$fooเป็นวิธีการประกาศตัวแปรในจาวาสคริปต์ในขณะที่var fooเป็นจริง
Camilo Martin

13

โดยไม่ต้องขยาย Array.prototype (กล่าวกันว่าเป็นการปฏิบัติที่ไม่ดี) หรือการใช้ jquery / underscore คุณสามารถทำได้ง่ายๆ filterใช้อาร์เรย์ได้

โดยการรักษาเหตุการณ์ล่าสุด:

    function arrayLastUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps last occurrence
            return c.indexOf(a, b + 1) < 0;
        });
    },

หรือเกิดขึ้นครั้งแรก:

    function arrayFirstUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps first occurrence
            return c.indexOf(a) === b;
        });
    },

มันเป็นเพียงจาวาสคริปต์ ECMAScript 5+ ซึ่งหมายถึงเฉพาะ IE9 + แต่มันดีสำหรับการพัฒนาในภาษา HTML / JS (แอพ Windows Store, Firefox OS, Sencha, Phonegap, Titanium, ... )


2
ความจริงที่ว่ามันคือ js 1.6 นั้นไม่ได้หมายความว่าคุณไม่สามารถใช้งานfilterได้ ที่หน้า MDNพวกเขามีการใช้งานสำหรับ Internet Explorer ฉันหมายถึงเบราว์เซอร์รุ่นเก่า นอกจากนี้: JS 1.6 อ้างถึงเอ็นจิ้น js ของ Firefox เท่านั้น แต่สิ่งที่ถูกต้องที่จะบอกว่ามันคือ ECMAScript 5
Camilo Martin

@CamiloMartin ฉันเปลี่ยน 1.6 เป็น ECMAScript5 ขอบคุณ
Cœur

13

มายากล

a.filter(e=>!(t[e]=e in t)) 

O (n) ประสิทธิภาพ ; เราถือว่าอาร์เรย์ของคุณอยู่ในและa t={}คำอธิบายที่นี่ (+ Jeppe impr.)


14
รูปลักษณ์นี้เจ๋งสุด ๆ โดยที่ไม่มีคำอธิบายที่ชัดเจนฉันตกลงคุณจะต้องขุด bitcoins เมื่อฉันรันสิ่งนี้
OndřejŽelazko

3
สิ่งที่ฉันหมายถึงคือคุณควรขยายคำตอบของคุณด้วยคำอธิบายและแสดงความคิดเห็นโครงสร้างของมัน อย่าคาดหวังว่าผู้คนจะพบคำตอบที่มีประโยชน์เช่นนี้ (แม้ว่ามันจะดูเจ๋งจริง ๆ น่าจะใช้ได้)
OndřejŽelazko

1
@Jeppe เมื่อฉันทำการปรับปรุงของคุณแล้วฉันพบaha effect (ก่อนที่ฉันจะไม่รู้ว่าฉันสามารถใช้inโอเปอเรเตอร์นอกการก่อสร้างอื่นนอกเหนือจากforลูป: P) - ขอบคุณ - ฉันขอบคุณมันและจะให้ +2 กับคำตอบที่ดีอื่น ๆ ของคุณ .
Kamil Kiełczewski

2
ไม่ได้สร้างตัวแปรทั่วโลกtที่ยังคงมีชีวิตอยู่หลังจากการกรอง…?
philipp

1
นี่เป็นทางออกที่ยุ่งยากจริงๆ น่าเสียดายที่คุณต้องประกาศนอกนิพจน์เว้นแต่ว่าคุณต้องการกำหนดตัวแปรโกลบอลและ / หรือพึ่งพาโมดูลบันเดิลของคุณเพื่อซ่อนโกลบอล มันดูแฟนซี แต่ทำด้วยตัวเอง (และทีมนักพัฒนาของคุณ) เป็นที่โปรดปรานและเพียงแค่เขียนสองซับแล้ว: let t = {}; a.filter (e =>! (t [e] = e ใน t))
ford04

13
[...new Set(duplicates)]

นี้เป็นหนึ่งในที่ง่ายและมีการอ้างอิงจากMDN เว็บเอกสาร

const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) // [2, 3, 4, 5, 6, 7, 32]

แม้ว่ารหัสนี้อาจแก้ปัญหาได้รวมถึงคำอธิบายว่าทำไมและวิธีแก้ปัญหานี้จะช่วยปรับปรุงคุณภาพการโพสต์ของคุณได้อย่างไรและอาจส่งผลให้คะแนนมากขึ้น จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตไม่ใช่เพียงแค่คนที่ถามตอนนี้ โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายและระบุข้อ จำกัด และสมมติฐานที่ใช้
id.ot

11

หากคุณใช้เฟรมเวิร์ก Prototype ไม่จำเป็นต้องทำลูป 'สำหรับ' คุณสามารถใช้http://www.prototypejs.org/api/array/uniqดังนี้

var a = Array.uniq();  

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

UNIQ ()

ฉันใช้

ขนาด()

และมีผลลัพธ์ที่เรียบง่ายของฉัน ป.ล. ขออภัยถ้าฉันทำสิ่งผิดพลาด

แก้ไข: หากคุณต้องการหลีกเลี่ยงการบันทึกที่ไม่ได้กำหนดคุณอาจต้องการเพิ่ม

(compact)

ก่อนหน้านี้เช่นนี้:

var a = Array.compact().uniq();  

14
เพราะฉันพบคำตอบที่ดีกว่าฉันคิดว่าหัวข้อนั้นมีไว้สำหรับทุกคนไม่ใช่เฉพาะกับคนที่ถาม
หลอกลวง

11

ตอนนี้ใช้ชุดคุณสามารถลบรายการที่ซ้ำกันและแปลงกลับเป็นอาร์เรย์

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

console.log([...new Set(names)])

อีกวิธีคือใช้ตัวเรียง & ตัวกรอง

var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];
var namesSorted = names.sort();
const result = namesSorted.filter((e, i) => namesSorted[i] != namesSorted[i+1]);
console.log(result);


10

นั่นเป็นเพราะ 0ค่าเท็จใน JavaScript

this[i] จะเป็นเท็จถ้าค่าของอาร์เรย์เป็น 0 หรือค่าเท็จอื่น ๆ


Ahhhh โอเคฉันเห็นแล้วตอนนี้ แต่จะมีวิธีแก้ไขที่ง่ายเพื่อให้ทำงานได้หรือไม่
Mottie

10
Array.prototype.getUnique = function() {
    var o = {}, a = []
    for (var i = 0; i < this.length; i++) o[this[i]] = 1
    for (var e in o) a.push(e)
    return a
}

ฉันคิดว่ามันจะไม่ทำงานถ้าอาร์เรย์มีวัตถุ / อาร์เรย์และฉันไม่แน่ใจว่ามันจะรักษาสเกลาร์ไว้หรือไม่
Camilo Martin

ใช่ทุกอย่างได้รับการทำให้เป็นก้อน ซึ่งสามารถแก้ไขได้โดยการเก็บค่าดั้งเดิมไว้ในoแทนที่จะเป็นเพียงแค่1แม้ว่าการเปรียบเทียบความเท่าเทียมกันจะยังคงเป็นแบบสตริง (แม้ว่าจะเท่ากับความเท่าเทียมกันของจาวาสคริปต์ทั้งหมด
ephemient

Array.prototype สามารถขยายได้ด้วยวิธีการที่ไม่นับจำนวนเท่านั้น .... Object.defineProperty (Array.prototype, "getUnique", {}) ... แต่ความคิดในการใช้วัตถุตัวช่วยนั้นดีมาก
bortunac

10

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

let objArr = [{
  id: '123'
}, {
  id: '123'
}, {
  id: '456'
}];

objArr = objArr.reduce((acc, cur) => [
  ...acc.filter((obj) => obj.id !== cur.id), cur
], []);

console.log(objArr);


9

คำตอบที่ง่ายที่สุดคือ:

const array = [1, 1, 2, 2, 3, 5, 5, 2];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // [1, 2, 3, 5]

เรียบง่าย แต่ใช้ไม่ได้กับอาเรย์ของวัตถุ
Thanwa Ch.

7

ฉันไม่แน่ใจว่าทำไม Gabriel Silveira เขียนฟังก์ชั่นแบบนั้น แต่รูปแบบที่เรียบง่ายกว่าที่เหมาะกับฉันเช่นกันโดยไม่มีการย่อคือ:

Array.prototype.unique = function() {
  return this.filter(function(value, index, array) {
    return array.indexOf(value, index + 1) < 0;
  });
};

หรือใน CoffeeScript:

Array.prototype.unique = ->
  this.filter( (value, index, array) ->
    array.indexOf(value, index + 1) < 0
  )

7

หากคุณโอเคที่มีการขึ้นต่อกันเป็นพิเศษหรือคุณมีหนึ่งในห้องสมุดใน codebase ของคุณอยู่แล้วคุณสามารถลบรายการที่ซ้ำกันออกจากอาร์เรย์โดยใช้ LoDash (หรือขีดล่าง)

การใช้

หากคุณยังไม่มีใน codebase ให้ติดตั้งโดยใช้ npm:

npm install lodash

จากนั้นใช้ดังต่อไปนี้:

import _ from 'lodash';
let idArray = _.uniq ([
    1,
    2,
    3,
    3,
    3
]);
console.dir(idArray);

ออก:

[ 1, 2, 3 ]

7

มีการตอบคำถามนี้จำนวนมาก แต่ไม่ได้ตอบสนองความต้องการเฉพาะของฉัน

คำตอบมากมายเช่นนี้

a.filter((item, pos, self) => self.indexOf(item) === pos);

แต่วิธีนี้ใช้ไม่ได้กับอาร์เรย์ของวัตถุที่ซับซ้อน

สมมติว่าเรามีอาร์เรย์ดังนี้:

const a = [
 { age: 4, name: 'fluffy' },
 { age: 5, name: 'spot' },
 { age: 2, name: 'fluffy' },
 { age: 3, name: 'toby' },
];

หากเราต้องการวัตถุที่มีชื่อเฉพาะเราควรใช้array.prototype.findIndexแทนarray.prototype.indexOf:

a.filter((item, pos, self) => self.findIndex(v => v.name === item.name) === pos);

วิธีแก้ปัญหาที่ดีเยี่ยมระวังว่าอาร์เรย์ใหม่จะกลับมาจากฟังก์ชัน (มันไม่ปรับเปลี่ยนเอง)
Thanwa Ch

6

จากShamasis Bhattacharyaบล็อก 's (ซับซ้อน O (2n) เวลา):

Array.prototype.unique = function() {
    var o = {}, i, l = this.length, r = [];
    for(i=0; i<l;i+=1) o[this[i]] = this[i];
    for(i in o) r.push(o[i]);
    return r;
};

จากบล็อกของPaul Irish : ปรับปรุง JQuery .unique():

(function($){

    var _old = $.unique;

    $.unique = function(arr){

        // do the default behavior only if we got an array of elements
        if (!!arr[0].nodeType){
            return _old.apply(this,arguments);
        } else {
            // reduce the array to contain no dupes via grep/inArray
            return $.grep(arr,function(v,k){
                return $.inArray(v,arr) === k;
            });
        }
    };
})(jQuery);

// in use..
var arr = ['first',7,true,2,7,true,'last','last'];
$.unique(arr); // ["first", 7, true, 2, "last"]

var arr = [1,2,3,4,5,4,3,2,1];
$.unique(arr); // [1, 2, 3, 4, 5]

6

การค้นหาค่า Array ที่ไม่ซ้ำใครในวิธีการง่ายๆ

function arrUnique(a){
  var t = [];
  for(var x = 0; x < a.length; x++){
    if(t.indexOf(a[x]) == -1)t.push(a[x]);
  }
  return t;
}
arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]

6

ดูเหมือนว่าเราได้สูญเสียคำตอบของราฟาเอลซึ่งเป็นคำตอบที่ยอมรับมาหลายปีแล้ว นี่คือ (อย่างน้อยในปี 2560) โซลูชันที่มีประสิทธิภาพดีที่สุดหากคุณไม่มีอาเรย์ผสม :

Array.prototype.getUnique = function(){
    var u = {}, a = [];
    for (var i = 0, l = this.length; i < l; ++i) {
        if (u.hasOwnProperty(this[i])) {
            continue;
        }
        a.push(this[i]);
        u[this[i]] = 1;
    }
return a;
}

ถ้าคุณทำมีผสมชนิดอาร์เรย์คุณสามารถเป็นอันดับที่สำคัญกัญชา:

Array.prototype.getUnique = function() {
    var hash = {}, result = [], key; 
    for ( var i = 0, l = this.length; i < l; ++i ) {
        key = JSON.stringify(this[i]);
        if ( !hash.hasOwnProperty(key) ) {
            hash[key] = true;
            result.push(this[i]);
        }
    }
    return result;
}

5

เพื่อแก้ไขปัญหาด้วยวิธีอื่น ๆ อาจเป็นประโยชน์หากไม่มีการทำซ้ำในขณะที่คุณโหลดอาร์เรย์วิธีที่Set object จะทำ แต่ยังไม่พร้อมใช้งานในเบราว์เซอร์ทั้งหมด ช่วยประหยัดหน่วยความจำและมีประสิทธิภาพมากขึ้นหากคุณต้องการดูเนื้อหาหลายครั้ง

Array.prototype.add = function (elem) {
   if (this.indexOf(elem) == -1) {
      this.push(elem);
   }
}

ตัวอย่าง:

set = [];
[1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); });

ให้คุณ set = [1,3,4,2]

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