Bacaan yang disyorkan: Nota kajian JavaScript: Menambah, memadam, mengubah suai dan menyemak tatasusunan
Kaedah Jumlah Tatasusunan Nota Kajian JavaScript
Nota Kajian JavaScript Susunan Susunan Rawak
Dalam temu bual, penemuduga sering bertanyakan soalan tentang melaksanakan penyahduplikasian tatasusunan dalam JavaScript Baru-baru ini, saya kebetulan mempelajari tentang tatasusunan JavaScript dan mengambil peluang ini untuk menyusun beberapa kaedah untuk menyahduplikasi tatasusunan dalam JavaScript.
Kaedah deduplikasi tatasusunan berikut telah dikumpulkan dan disusun oleh saya sendiri Jika terdapat sebarang ralat, sila nyatakan ralat dalam teks.
Penyahduplikasi gelung berganda
Kaedah ini menggunakan dua gelung untuk traversal. Keseluruhan idea ialah:
Bina tatasusunan kosong untuk menyimpan tatasusunan nyahduplikasi
Gelung luar untuk merentasi tatasusunan asal, mengeluarkan elemen daripada tatasusunan setiap kali dan membandingkannya dengan tatasusunan hasil
Jika elemen yang dikeluarkan daripada tatasusunan asal adalah sama dengan elemen dalam tatasusunan hasil, keluarkan daripada gelung jika tidak, simpannya dalam tatasusunan hasil
Kod adalah seperti berikut:
Array.prototype.unique1 = function () { // 构建一个新数组,存放结果 var newArray = [this[0]]; // for循环,每次从原数组中取出一个元素 // 用取出的元素循环与结果数组对比 for (var i = 1; i < this.length; i++) { var repeat = false; for (var j=0; j < newArray.length; j++) { // 原数组取出的元素与结果数组元素相同 if(this[i] == newArray[j]) { repeat = true; break; } } if(!repeat) { // 如果结果数组中没有该元素,则存放到结果数组中 newArray.push(this[i]); } } return newArray; }
Andaikan kita mempunyai tatasusunan seperti ini:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1',`2`]; arr.unique1(); // [1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5]
Dikatakan kaedah ini memakan masa dan berintensif prestasi. Hanya lakukan ujian mudah (kaedah ujian ditulis dengan buruk):
function test () { var arr = []; for (var i = 0; i < 1000000; i++) { arr.push(Math.round(Math.random(i) * 10000)); } doTest(arr, 1); } function doTest(arr, n) { var tStart = (new Date()).getTime(); var re = arr.unique1(); var tEnd = (new Date()).getTime(); console.log('双重循环去重方法使用时间是:' + (tEnd - tStart) + 'ms'); return re; } test();
Jalankan kod di atas dalam pengawal Chrome dan uji masa yang diambil untuk penyahduaan gelung berganda: 11031ms.
Kaedah di atas boleh disimulasikan menggunakan kaedah forEach() dan kaedah indexOf():
function unique1() { var newArray = []; this.forEach(function (index) { if (newArray.indexOf(index) == -1) { newArray.push(index); } }); return newArray; }
Panggilan melalui unique1.apply(arr) atau unique1.call(arr). Walau bagaimanapun, kaedah ini jauh lebih cekap Kod ujian yang sama di atas mengambil masa 5423ms, yang hampir separuh daripada pantas.
Isih traversal untuk mengalih keluar pendua
Mula-mula gunakan kaedah sort() untuk mengisih tatasusunan asal Selepas mengisih, merentasi tatasusunan dan semak sama ada elemen ke-i dalam tatasusunan adalah sama dengan elemen terakhir dalam tatasusunan hasil. Jika berbeza, elemen diletakkan ke dalam tatasusunan yang terhasil.
Array.prototype.unique2 = function () { // 原数组先排序 this.sort(); // 构建一个新数组存放结果 var newArray = []; for (var i = 1; i < this.length; i++) { // 检查原数中的第i个元素与结果中的最后一个元素是否相同 // 因为排序了,所以重复元素会在相邻位置 if(this[i] !== newArray[newArray.length - 1]) { // 如果不同,将元素放到结果数组中 newArray.push(this[i]); } } return newArray; }
Contohnya:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique2(); // ["1", 1, 2, "2", 3, 32, 34, 4, 5, 56, "a", "b", "c"]
Kaedah ini mempunyai dua ciri:
Tatasusunan selepas penyahduplikasian akan diisih, terutamanya kerana nombor asal telah diisih sebelum penyahduplikasian
Dalam tatasusunan selepas penyahduaan, aksara angka yang sama dengan nombor tidak boleh dibezakan, seperti '1' dan 1
Menggunakan kaedah yang sama, masa ujian ialah: 1232ms.
Kaedah pasangan nilai kunci objek
Idea pelaksanaan kaedah deduplikasi ini ialah:
Buat objek JavaScript dan tatasusunan baharu
Gunakan gelung for untuk melintasi tatasusunan asal, mengeluarkan satu elemen setiap kali dan membandingkannya dengan kunci objek JavaScript
Jika ia tidak disertakan, tolak nilai elemen yang disimpan dalam objek ke dalam tatasusunan hasil, dan tetapkan nilai nama atribut yang disimpan dalam objek objek kepada 1
Kod adalah seperti berikut:
Array.prototype.unique3 = function () { // 构建一个新数组存放结果 var newArray = []; // 创建一个空对象 var object = {}; // for循环时,每次取出一个元素与对象进行对比 // 如果这个元素不重复,则将它存放到结果数中 // 同时把这个元素的内容作为对象的一个属性,并赋值为1, // 存入到第2步建立的对象中 for (var i = 0; i < this.length; i++){ // 检测在object对象中是否包含遍历到的元素的值 if(!object[typeof(this[i]) + this[i]]) { // 如果不包含,将存入对象的元素的值推入到结果数组中 newArray.push(this[i]); // 如果不包含,存入object对象中该属性名的值设置为1 object[typeof(this[i]) + this[i]] = 1; } } return newArray; }
Jalankan contoh sebelumnya:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique3(); // [1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"]
Begitu juga, kunci yang berbeza mungkin disalah anggap sama; sebagai contoh: a[1], a["1"] . Masa yang diambil dengan kaedah ini: 621ms. Kaedah ini mengambil masa yang paling singkat, tetapi mengambil lebih banyak ingatan.
Selain kaedah di atas, terdapat beberapa kaedah lain seperti berikut:
// 方法四 Array.prototype.unique4 = function () { // 构建一个新数组存放结果 var newArray = []; // 遍历整个数组 for (var i = 0; i < this.length; i++) { // 遍历是否有重复的值 for (j = i + 1; j < this.length; j++) { // 如果有相同元素,自增i变量,跳出i的循环 if(this[i] === this[j]) { j = ++i; } } // 如果没有相同元素,将元素推入到结果数组中 newArray.push(this[i]); } return newArray; }
Keputusan ujian Chrome
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique4(); // ["a", 1, 3, 4, 56, 32, 34, 2, "b", "c", 5, "1", "2"]
Begitu juga, 1 dan '1' tidak dapat dibezakan.
// 方法五 Array.prototype.unique5 = function () { // 构建一个新数组存放结果 var newArray = []; // 遍历整个数组 for (var i = 0; i < this.length; i++) { // 如果当前数组的第i值保存到临时数组,那么跳过 var index = this[i]; // 如果数组项不在结果数组中,将这个值推入结果数组中 if (newArray.indexOf(index) === -1) { newArray.push(index); } } return newArray; }
Keputusan ujian Chrome:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique6(); // [1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"]
Begitu juga, 1 dan '1' tidak dapat dibezakan. Masa yang dihabiskan: 14361ms.
// 方法六 Array.prototype.unique6 = function () { return this.reduce(function (newArray, index) { if(newArray.indexOf(index) < 0) { newArray.push(index); } return newArray; },[]); }
Keputusan ujian adalah seperti berikut:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique6(); // [1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"]
Masa diambil: 16490ms.
// 方法七 Array.prototype.unique7 = function(){ var newArray; newArray = this.filter(function (ele,i,arr) { return arr.indexOf(ele) === i; }); return newArray; }
Keputusan ujian:
var arr = [1,2,3,4,'a','b',1,3,4,56,32,34,2,'b','c',5,'1','2']; arr.unique6(); // [1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"]
Masa diambil: 13201ms.
Walaupun terdapat banyak kaedah, secara perbandingan, kaedah berikut adalah penyelesaian yang lebih baik:
Array.prototype.unique3 = function () { // 构建一个新数组存放结果 var newArray = []; // 创建一个空对象 var object = {}; // for循环时,每次取出一个元素与对象进行对比 // 如果这个元素不重复,则将它存放到结果数中 // 同时把这个元素的内容作为对象的一个属性,并赋值为1, // 存入到第2步建立的对象中 for (var i = 0; i < this.length; i++){ // 检测在object对象中是否包含遍历到的元素的值 if(!object[typeof(this[i]) + this[i]]) { // 如果不包含,将存入对象的元素的值推入到结果数组中 newArray.push(this[i]); // 如果不包含,存入object对象中该属性名的值设置为1 object[typeof(this[i]) + this[i]] = 1; } } return newArray; }
Tetapi terdapat penyelesaian yang lebih ringkas dan dioptimumkan untuk penyahduplikasian dalam ES6, seperti:
// ES6 function unique (arr) { const seen = new Map() return arr.filter((a) => !seen.has(a) && seen.set(a, 1)) } // or function unique (arr) { return Array.from(new Set(arr)) }
Di atas ialah nota pembelajaran JavaScript yang diperkenalkan oleh editor untuk mengalih keluar pendua daripada tatasusunan saya harap ia akan membantu anda!